Back to index

gcompris  8.2.2
draw.c
Go to the documentation of this file.
00001  /* gcompris - draw.c
00002  *
00003  * Time-stamp: <2001/08/20 00:54:45 bruno>
00004  *
00005  * Copyright (C) 2000 Bruno Coudoin
00006  *
00007  *   This program is free software; you can redistribute it and/or modify
00008  *   it under the terms of the GNU General Public License as published by
00009  *   the Free Software Foundation; either version 2 of the License, or
00010  *   (at your option) any later version.
00011  *
00012  *   This program is distributed in the hope that it will be useful,
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *   GNU General Public License for more details.
00016  *
00017  *   You should have received a copy of the GNU General Public License
00018  *   along with this program; if not, write to the Free Software
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 /* libxml includes */
00023 #include <libxml/tree.h>
00024 #include <libxml/parser.h>
00025 
00026 #include <math.h>
00027 #include <string.h>
00028 
00029 #include "gcompris/gcompris.h"
00030 #include "gcompris/pixbuf_util.h"
00031 
00032 #define SOUNDLISTFILE PACKAGE
00033 #define FILE_SELECTOR_ROOT "drawings"
00034 
00035 /* Represent the drawing area */
00036 static gint drawing_area_x1 = 0;
00037 static gint drawing_area_y1 = 0;
00038 static gint drawing_area_x2 = 0;
00039 static gint drawing_area_y2 = 0;
00040 
00041 /* Set the grid size. If 0 then no grid */
00042 static gint grid_step = 0;
00043 static GnomeCanvasItem      *gridItem = NULL;
00044 static GnomeCanvasItem      *grid_root_item = NULL;
00045 #define DEFAULT_GRID_STEP 20
00046 
00047 /* Needed to keep a temporary location of the user click */
00048 static double clicked_x, clicked_y;
00049 
00050 static GcomprisBoard *gcomprisBoard = NULL;
00051 static GnomeCanvasItem      *shape_root_item = NULL;
00052 static GnomeCanvasItem      *draw_root_item = NULL;
00053 static GnomeCanvasItem      *current_color_item = NULL;
00054 static guint          currentColor = 0;
00055 static gboolean              board_paused = TRUE;
00056 
00057 typedef enum
00058   {
00059     TOOL_SAVE        = 0,
00060     TOOL_LOAD        = 1,
00061     TOOL_RECT        = 2,
00062     TOOL_FILLED_RECT = 3,
00063     TOOL_CIRCLE             = 4,
00064     TOOL_FILLED_CIRCLE      = 5,
00065     TOOL_LINE        = 6,
00066     TOOL_IMAGE              = 7,
00067     TOOL_TEXT        = 8,
00068     TOOL_GRID        = 9,
00069     TOOL_DELETE             = 10,
00070     TOOL_FILL        = 11,
00071     TOOL_RAISE              = 12,
00072     TOOL_LOWER              = 13,
00073     TOOL_SELECT             = 14,
00074     TOOL_FLIP        = 15,
00075     TOOL_ROTATE_CCW  = 16,
00076     TOOL_ROTATE_CW   = 17,
00077   } ToolList;
00078 
00079 #define NUMBER_OF_TOOL      TOOL_ROTATE_CW + 1
00080 
00081 static ToolList              currentTool = TOOL_RECT;
00082 static GnomeCanvasItem      *currentToolItem = NULL;
00083 static GnomeCanvasItem      *selectionToolItem = NULL;
00084 
00085 // Used to cross reference pixmap for the tools
00086 static char *tool_pixmap_name[] =
00087   {
00088     "draw/tool-save.png",            "draw/tool-save.png",
00089     "draw/tool-load.png",            "draw/tool-load.png",
00090     "draw/tool-rectangle.png",       "draw/tool-rectangle_on.png",
00091     "draw/tool-filledrectangle.png", "draw/tool-filledrectangle_on.png",
00092     "draw/tool-circle.png",          "draw/tool-circle_on.png",
00093     "draw/tool-filledcircle.png",    "draw/tool-filledcircle_on.png",
00094     "draw/tool-line.png",            "draw/tool-line_on.png",
00095     "draw/tool-image.png",           "draw/tool-image_on.png",
00096     "draw/tool-text.png",            "draw/tool-text_on.png",
00097     "draw/tool-grid.png",            "draw/tool-grid_on.png",
00098     "draw/tool-del.png",             "draw/tool-del_on.png",
00099     "draw/tool-fill.png",            "draw/tool-fill_on.png",
00100     "draw/tool-up.png",              "draw/tool-up_on.png",
00101     "draw/tool-down.png",            "draw/tool-down_on.png",
00102     "draw/tool-select.png",          "draw/tool-select_on.png",
00103     "draw/tool-flip.png",            "draw/tool-flip_on.png",
00104     "draw/tool-rotation-ccw.png",    "draw/tool-rotation-ccw_on.png",
00105     "draw/tool-rotation-cw.png",     "draw/tool-rotation-cw_on.png"
00106   };
00107 
00108 #define PIXMAP_OFF 0
00109 #define PIXMAP_ON  1
00110 
00111 /*
00112  * A Single Point
00113  */
00114 typedef struct {
00115   double         x;
00116   double         y;
00117 } Point;
00118 
00119 /*
00120  * Contains the points that represents the anchors
00121  */
00122 typedef struct {
00123   GnomeCanvasItem *rootitem;
00124   ToolList      tool;
00125   GnomeCanvasItem *item;
00126   GnomeCanvasItem *nw;
00127   GnomeCanvasItem *n;
00128   GnomeCanvasItem *ne;
00129   GnomeCanvasItem *e;
00130   GnomeCanvasItem *w;
00131   GnomeCanvasItem *sw;
00132   GnomeCanvasItem *s;
00133   GnomeCanvasItem *se;
00134   double         ref_x1;
00135   double         ref_y1;
00136   double         ref_x2;
00137   double         ref_y2;
00138 } AnchorsItem;
00139 
00140 typedef enum
00141   {
00142     ANCHOR_NW        = 1,
00143     ANCHOR_N         = 2,
00144     ANCHOR_NE        = 3,
00145     ANCHOR_E         = 4,
00146     ANCHOR_W         = 5,
00147     ANCHOR_SW        = 6,
00148     ANCHOR_S         = 7,
00149     ANCHOR_SE        = 8,
00150   } AnchorType;
00151 
00152 #define ANCHOR_COLOR        0x36ede480
00153 #define DEFAULT_ITEM_SIZE   40
00154 #define DEFAULT_ANCHOR_SIZE 8
00155 static AnchorsItem *selected_anchors_item = NULL;
00156 
00157 #define DRAW_WIDTH_PIXELS   6
00158 
00159 #define GRID_COLOR          0XCECECEFF
00160 
00161 #define MAX_TEXT_CHAR              50
00162 
00163 /* Defines the displayed colors in the color selector */
00164 static guint ext_colorlist [] =
00165   {
00166     0x000000FF, 0x202020FF, 0x404040FF, 0x505050FF, 
00167     0x815a38FF, 0xb57c51FF, 0xe5a370FF, 0xfcc69cFF, 
00168     0xb20c0cFF, 0xea2c2cFF, 0xf26363FF, 0xf7a3a3FF, 
00169     0xff6600FF, 0xff8a3dFF, 0xfcaf7bFF, 0xf4c8abFF, 
00170     0x9b8904FF, 0xd3bc10FF, 0xf4dd2cFF, 0xfcee85FF, 
00171     0x255b0cFF, 0x38930eFF, 0x56d11dFF, 0x8fe268FF, 
00172     0x142f9bFF, 0x2d52e5FF, 0x667eddFF, 0xa6b4eaFF, 
00173     0x328989FF, 0x37b2b2FF, 0x3ae0e0FF, 0x96e0e0FF, 
00174     0x831891FF, 0xc741d8FF, 0xde81eaFF, 0xeecdf2FF, 
00175     0x666666FF, 0x838384FF, 0xc4c4c4FF, 0xffffffFF, 
00176   };
00177 
00178 static void    start_board (GcomprisBoard *agcomprisBoard);
00179 static void    pause_board (gboolean pause);
00180 static void    end_board (void);
00181 static gint    key_press(guint keyval, gchar *commit_str, gchar *preedit_str);
00182 static gboolean       is_our_board (GcomprisBoard *gcomprisBoard);
00183 static void    config(void);
00184 
00185 static void    draw_destroy_all_items(void);
00186 static void    draw_next_level(void);
00187 static ToolList       get_tool(GnomeCanvasItem *item);
00188 static void    create_anchors(GnomeCanvasItem *item);
00189 static void    display_anchors(AnchorsItem *anchorsItem, gboolean visible);
00190 static void    display_color_selector(GnomeCanvasGroup *parent);
00191 static void    display_tool_selector(GnomeCanvasGroup *parent);
00192 static void    display_drawing_area(GnomeCanvasGroup *parent);
00193 static void    display_grid(gboolean status);
00194 static gint    ext_color_event(GnomeCanvasItem *item, GdkEvent *event, gpointer color_rgba);
00195 static void    set_current_tool(GnomeCanvasItem *item, gint tool);
00196 static gint    tool_event(GnomeCanvasItem *item, GdkEvent *event, gint tool);
00197 static void    set_selected_item(AnchorsItem *anchorsItem);
00198 static gint    item_event(GnomeCanvasItem *item, GdkEvent *event, void *shape);
00199 static gint    item_event_resize(GnomeCanvasItem *item, GdkEvent *event, AnchorsItem *anchorsItem);
00200 static gint    item_event_move(GnomeCanvasItem *item, GdkEvent *event, AnchorsItem *anchorsItem);
00201 static void    highlight_color_item(GnomeCanvasItem *item);
00202 static guint   get_tool_cursor(ToolList tool);
00203 static guint   get_resize_cursor(AnchorType anchor);
00204 static void    snap_to_grid(double *x, double *y);
00205 static void    image_selected(gchar *image);
00206 static void    load_drawing(gchar *file, gchar *type);
00207 static void    save_drawing(gchar *file, gchar *type);
00208 
00209 /* Description of this plugin */
00210 static BoardPlugin menu_bp =
00211   {
00212     NULL,
00213     NULL,
00214     "A simple vector drawing tool",
00215     "Creative board where you can draw freely",
00216     "Bruno Coudoin <bruno.coudoin@free.fr>",
00217     NULL,
00218     NULL,
00219     NULL,
00220     NULL,
00221     start_board,
00222     pause_board,
00223     end_board,
00224     is_our_board,
00225     key_press,
00226     NULL,
00227     NULL,
00228     config,
00229     NULL,
00230     NULL,
00231     NULL
00232   };
00233 
00234 /*
00235  * Main entry point mandatory for each Gcompris's game
00236  * ---------------------------------------------------
00237  *
00238  */
00239 
00240 GET_BPLUGIN_INFO(draw)
00241 
00242 /*
00243  * in : boolean TRUE = PAUSE : FALSE = CONTINUE
00244  *
00245  */
00246 static void pause_board (gboolean pause)
00247 {
00248   if(gcomprisBoard==NULL)
00249     return;
00250 
00251   board_paused = pause;
00252 
00253 }
00254 
00255 /*
00256  */
00257 static void start_board (GcomprisBoard *agcomprisBoard)
00258 {
00259 
00260   if(agcomprisBoard!=NULL)
00261     {
00262       gchar *img;
00263 
00264       gcomprisBoard=agcomprisBoard;
00265 
00266       /* disable im_context */
00267       gcomprisBoard->disable_im_context = TRUE;
00268 
00269       img = gc_skin_image_get("gcompris-bg.jpg");
00270       gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), 
00271                            img);
00272       g_free(img);
00273 
00274 
00275       /* set initial values for this level */
00276       gcomprisBoard->level = 1;
00277       gcomprisBoard->maxlevel=1;
00278       gc_bar_set(0);
00279 
00280       gcomprisBoard->number_of_sublevel=0;
00281       gcomprisBoard->sublevel = 0;
00282 
00283       drawing_area_x1 = 124;
00284       drawing_area_y1 = 20;
00285       drawing_area_x2 = gcomprisBoard->width  - 15;
00286       drawing_area_y2 = gcomprisBoard->height - 78;
00287 
00288       gc_bar_set(0);
00289 
00290       draw_next_level();
00291 
00292       /* Special Init for this board */
00293       selected_anchors_item = NULL;
00294 
00295       pause_board(FALSE);
00296 
00297     }
00298 
00299 }
00300 
00301 static void
00302 end_board ()
00303 {
00304 
00305   if(gcomprisBoard!=NULL)
00306     {
00307       gc_cursor_set(GCOMPRIS_DEFAULT_CURSOR);
00308       pause_board(TRUE);
00309       draw_destroy_all_items();
00310       gcomprisBoard->level = 1;       // Restart this game to zero
00311     }
00312   gcomprisBoard = NULL;
00313 }
00314 
00315 /* Get the user keys to use with the text tool */
00316 static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str)
00317 {
00318   char str[2];
00319   char utf8char[6];
00320 
00321   GnomeCanvasItem    *item = NULL;
00322 
00323   if(!gcomprisBoard)
00324     return TRUE;
00325 
00326   /* Add some filter for control and shift key */
00327   switch (keyval)
00328     {
00329     case GDK_F1:
00330       gc_selector_file_load(gcomprisBoard, FILE_SELECTOR_ROOT, "", load_drawing);
00331       break;
00332     case GDK_F2:
00333       gc_selector_file_save(gcomprisBoard, FILE_SELECTOR_ROOT, "", save_drawing);
00334       break;
00335     case GDK_Shift_L:
00336     case GDK_Shift_R:
00337     case GDK_Control_L:
00338     case GDK_Control_R:
00339     case GDK_Caps_Lock:
00340     case GDK_Shift_Lock:
00341     case GDK_Meta_L:
00342     case GDK_Meta_R:
00343     case GDK_Alt_L:
00344     case GDK_Alt_R:
00345     case GDK_Super_L:
00346     case GDK_Super_R:
00347     case GDK_Hyper_L:
00348     case GDK_Hyper_R:
00349     case GDK_Mode_switch:
00350     case GDK_dead_circumflex:
00351     case GDK_Num_Lock:
00352       return FALSE;
00353     }
00354 
00355   if(selected_anchors_item == NULL)
00356     return TRUE;
00357 
00358   sprintf(utf8char, "%c", gdk_keyval_to_unicode(keyval));
00359 
00360   g_unichar_to_utf8 (gdk_keyval_to_unicode(keyval),
00361                    utf8char);
00362 
00363   sprintf(str, "%c", keyval);
00364 
00365   item = selected_anchors_item->item;
00366 
00367   if(GNOME_IS_CANVAS_TEXT(item))
00368     {
00369       gchar *oldtext;
00370       gchar *newtext;
00371 
00372       gtk_object_get (GTK_OBJECT (item), "text", &oldtext, NULL);
00373 
00374       switch(keyval)
00375        {
00376        case GDK_BackSpace:
00377        case GDK_Delete:
00378          if(oldtext[1] != '\0') {
00379            gchar *ptr;
00380            ptr = g_utf8_prev_char(oldtext+g_utf8_strlen(oldtext, MAX_TEXT_CHAR)+1);
00381            *ptr = '\0';
00382            newtext = g_strdup(oldtext);
00383          } else
00384            newtext = "?";
00385 
00386          break;
00387 
00388        default:
00389 
00390          if(oldtext[0] == '?' && strlen(oldtext)==1)
00391            {
00392              oldtext[0] = ' ';
00393              g_strstrip(oldtext);
00394            }
00395 
00396          if(strlen(oldtext)<MAX_TEXT_CHAR)
00397            newtext = g_strconcat(oldtext, &utf8char, NULL);
00398          else
00399            newtext = g_strdup(oldtext);
00400          break;
00401 
00402        }
00403 
00404       gnome_canvas_item_set (item,
00405                           "text", newtext,
00406                           NULL);
00407 
00408       g_free(oldtext);
00409     }
00410 
00411   return TRUE;
00412 }
00413 
00414 
00415 
00416 static gboolean
00417 is_our_board (GcomprisBoard *gcomprisBoard)
00418 {
00419   if (gcomprisBoard)
00420     {
00421       if(g_strcasecmp(gcomprisBoard->type, "draw")==0)
00422        {
00423          /* Set the plugin entry */
00424          gcomprisBoard->plugin=&menu_bp;
00425 
00426          return TRUE;
00427        }
00428     }
00429   return FALSE;
00430 }
00431 
00432 static void
00433 config ()
00434 {
00435   if(gcomprisBoard!=NULL)
00436     {
00437       pause_board(TRUE);
00438     }
00439 }
00440 
00441 /*-------------------------------------------------------------------------------*/
00442 /*-------------------------------------------------------------------------------*/
00443 /*-------------------------------------------------------------------------------*/
00444 /*-------------------------------------------------------------------------------*/
00445 
00446 /* set initial values for the next level */
00447 static void draw_next_level()
00448 {
00449 
00450   gc_bar_set_level(gcomprisBoard);
00451 
00452   draw_destroy_all_items();
00453 
00454   shape_root_item = \
00455     gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
00456                         gnome_canvas_group_get_type (),
00457                         "x", (double)0,
00458                         "y", (double)0,
00459                         NULL);
00460 
00461   display_color_selector(GNOME_CANVAS_GROUP(shape_root_item));
00462   display_tool_selector(GNOME_CANVAS_GROUP(shape_root_item));
00463   display_drawing_area(GNOME_CANVAS_GROUP(shape_root_item));
00464 
00465 }
00466 
00467 
00468 static void display_drawing_area(GnomeCanvasGroup *parent)
00469 {
00470   GnomeCanvasItem *item = NULL;
00471 
00472   item = gnome_canvas_item_new (parent,
00473                             gnome_canvas_rect_get_type (),
00474                             "x1", (double) drawing_area_x1,
00475                             "y1", (double) drawing_area_y1,
00476                             "x2", (double) drawing_area_x2,
00477                             "y2", (double) drawing_area_y2,
00478                             "fill_color", "white",
00479                             NULL);
00480   gtk_signal_connect(GTK_OBJECT(item), "event",
00481                    (GtkSignalFunc) item_event,
00482                    NULL);
00483 
00484   display_grid(FALSE);
00485 
00486   draw_root_item = \
00487     gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_root_item),
00488                         gnome_canvas_group_get_type (),
00489                         "x", (double)0,
00490                         "y", (double)0,
00491                         NULL);
00492 
00493 }
00494 
00495 static void display_color_selector(GnomeCanvasGroup *parent)
00496 {
00497   GdkPixbuf *pixmap;
00498   GnomeCanvasItem *item = NULL;
00499   gint x  = 0;
00500   gint y  = 0;
00501   gint x1 = 0;
00502   gint c  = 0;
00503   guint color_pixmap_height = 0;
00504 
00505   pixmap = gc_pixmap_load("draw/color-selector.png");
00506   if(pixmap)
00507     {
00508       x = (drawing_area_x2 - drawing_area_x1
00509           - gdk_pixbuf_get_width(pixmap))/2
00510        + drawing_area_x1;
00511 
00512       color_pixmap_height = gdk_pixbuf_get_height(pixmap);
00513       y = gcomprisBoard->height - color_pixmap_height - 5;
00514 
00515       item = gnome_canvas_item_new (parent,
00516                                 gnome_canvas_pixbuf_get_type (),
00517                                 "pixbuf", pixmap,
00518                                 "x", (double) x,
00519                                 "y", (double) y,
00520                                 NULL);
00521       gdk_pixbuf_unref(pixmap);
00522     }
00523 
00524   for(x1=x+26; x1<(x+26)+55*10; x1+=56)
00525     {
00526       item = gnome_canvas_item_new (parent,
00527                                 gnome_canvas_rect_get_type (),
00528                                 "x1", (double) x1,
00529                                 "y1", (double) y + 8,
00530                                 "x2", (double) x1 + 24,
00531                                 "y2", (double) y + color_pixmap_height/2,
00532                                 "fill_color_rgba", ext_colorlist[c*4],
00533                                 "outline_color_rgba", 0x07a3e080,
00534                                 NULL);
00535       gtk_signal_connect(GTK_OBJECT(item), "event",
00536                       (GtkSignalFunc) ext_color_event,
00537                       GINT_TO_POINTER(ext_colorlist[c*4]));
00538 
00539       if(c==0)
00540        highlight_color_item(item);
00541 
00542       item = gnome_canvas_item_new (parent,
00543                                 gnome_canvas_rect_get_type (),
00544                                 "x1", (double) x1 + 26,
00545                                 "y1", (double) y + 8,
00546                                 "x2", (double) x1 + 50,
00547                                 "y2", (double) y + color_pixmap_height/2,
00548                                 "fill_color_rgba", ext_colorlist[c*4+1],
00549                                 "outline_color_rgba", 0x07a3e080,
00550                                 NULL);
00551       gtk_signal_connect(GTK_OBJECT(item), "event",
00552                       (GtkSignalFunc) ext_color_event,
00553                       GINT_TO_POINTER(ext_colorlist[c*4+1]));
00554 
00555       item = gnome_canvas_item_new (parent,
00556                                 gnome_canvas_rect_get_type (),
00557                                 "x1", (double) x1,
00558                                 "y1", (double) y + color_pixmap_height/2 + 2,
00559                                 "x2", (double) x1 + 24,
00560                                 "y2", (double) y + color_pixmap_height - 8,
00561                                 "fill_color_rgba", ext_colorlist[c*4+2],
00562                                 "outline_color_rgba", 0x07a3e080,
00563                                 NULL);
00564       gtk_signal_connect(GTK_OBJECT(item), "event",
00565                       (GtkSignalFunc) ext_color_event,
00566                       GINT_TO_POINTER(ext_colorlist[c*4+2]));
00567 
00568       item = gnome_canvas_item_new (parent,
00569                                 gnome_canvas_rect_get_type (),
00570                                 "x1", (double) x1 + 26,
00571                                 "y1", (double) y + color_pixmap_height/2 + 2,
00572                                 "x2", (double) x1 + 50,
00573                                 "y2", (double) y + color_pixmap_height - 8,
00574                                 "fill_color_rgba", ext_colorlist[c*4+3],
00575                                 "outline_color_rgba", 0x07a3e080,
00576                                 NULL);
00577       gtk_signal_connect(GTK_OBJECT(item), "event",
00578                       (GtkSignalFunc) ext_color_event,
00579                       GINT_TO_POINTER(ext_colorlist[c*4+3]));
00580 
00581       c++;
00582     }
00583 
00584   currentColor = ext_colorlist[0];
00585 }
00586 
00587 #define SELECTOR_VERTICAL_SPACING 52
00588 
00589 static void display_tool_selector(GnomeCanvasGroup *parent)
00590 {
00591   GdkPixbuf *pixmap;
00592   GnomeCanvasItem *item = NULL;
00593   gint x   = 0;
00594   gint x2  = 0;
00595   gint y   = 0;
00596   guint toolIndex = 0;
00597 
00598   pixmap = gc_pixmap_load("draw/tool-selector.png");
00599   if(pixmap)
00600     {
00601       x = 3;
00602       y = drawing_area_y1;
00603       item = gnome_canvas_item_new (parent,
00604                                 gnome_canvas_pixbuf_get_type (),
00605                                 "pixbuf", pixmap,
00606                                 "x", (double) x,
00607                                 "y", (double) y,
00608                                 NULL);
00609       gdk_pixbuf_unref(pixmap);
00610     }
00611 
00612   y += 15;
00613   x  = 10;
00614   x2 = 55;
00615   pixmap = gc_pixmap_load(tool_pixmap_name[0 + PIXMAP_ON]);
00616   if(pixmap)
00617     {
00618       item = gnome_canvas_item_new (parent,
00619                                 gnome_canvas_pixbuf_get_type (),
00620                                 "pixbuf", pixmap,
00621                                 "x", (double) x,
00622                                 "y", (double) y,
00623                                 "width", (double) 40.0,
00624                                 "height", (double) 40.0,
00625                                 "width_set", TRUE,
00626                                 "height_set", TRUE,
00627                                 NULL);
00628       gdk_pixbuf_unref(pixmap);
00629 
00630       gtk_signal_connect(GTK_OBJECT(item), "event",
00631                       (GtkSignalFunc) tool_event,
00632                       GINT_TO_POINTER(TOOL_SAVE) );
00633 
00634     }
00635   currentTool = TOOL_SAVE;
00636   currentToolItem = item;
00637 
00638   for( toolIndex = 1 ; toolIndex < NUMBER_OF_TOOL ; toolIndex++)
00639     {
00640       y += (toolIndex%2 == 0 ? SELECTOR_VERTICAL_SPACING : 0);
00641       pixmap = gc_pixmap_load(tool_pixmap_name[(2*toolIndex) + PIXMAP_OFF]);
00642 
00643       if(pixmap)
00644        {
00645          item = gnome_canvas_item_new (parent,
00646                                    gnome_canvas_pixbuf_get_type (),
00647                                    "pixbuf", pixmap,
00648                                    "x", (double) (toolIndex%2 == 0 ? x : x2),
00649                                    "y", (double) y,
00650                                    "width", (double) 40.0,
00651                                    "height", (double) 40.0,
00652                                    "width_set", TRUE,
00653                                    "height_set", TRUE,
00654                                    NULL);
00655          gdk_pixbuf_unref(pixmap);
00656 
00657          switch(toolIndex)
00658            {
00659            case TOOL_GRID:
00660              gridItem = item;
00661              break;
00662            case TOOL_SELECT:
00663              selectionToolItem = item;
00664              break;
00665            default:
00666              break;
00667            }
00668 
00669          gtk_signal_connect(GTK_OBJECT(item), "event",
00670                           (GtkSignalFunc) tool_event,
00671                           GINT_TO_POINTER(toolIndex));
00672        }
00673     }
00674 }
00675 
00676 /*
00677  * Request the display of the grid if status is true
00678  *
00679  */
00680 static void display_grid(gboolean status)
00681 {
00682   guint x, y;
00683   GdkPixbuf *pixmap = NULL;
00684 
00685   pixmap = gc_pixmap_load(tool_pixmap_name[(TOOL_GRID*2) +
00686                                            (status == TRUE ? PIXMAP_ON : PIXMAP_OFF)]);
00687   if(pixmap)
00688     {
00689       gnome_canvas_item_set (gridItem,
00690                           "pixbuf", pixmap,
00691                           NULL);
00692       gdk_pixbuf_unref(pixmap);
00693     }
00694 
00695   if(!status)
00696     {
00697       grid_step = 0;
00698 
00699       if(grid_root_item!=NULL)
00700        gnome_canvas_item_hide(grid_root_item);
00701       return;
00702     }
00703 
00704   grid_step = DEFAULT_GRID_STEP;
00705 
00706   if(grid_root_item!=NULL)
00707     {
00708       gnome_canvas_item_show(grid_root_item);
00709       return;
00710     }
00711 
00712   /* Creation of the grid */
00713 
00714   grid_root_item = \
00715     gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_root_item),
00716                         gnome_canvas_group_get_type (),
00717                         "x", (double)0,
00718                         "y", (double)0,
00719                         NULL);
00720   gnome_canvas_item_raise_to_top(grid_root_item);
00721   //  gnome_canvas_item_raise(grid_root_item, 50);
00722 
00723   for( x = drawing_area_x1 ; x < drawing_area_x2 ; x += grid_step)
00724     {
00725       GnomeCanvasPoints     *points;
00726       GnomeCanvasItem       *item;
00727 
00728       for( y = drawing_area_y1 ; y < drawing_area_y2 ; y += grid_step)
00729        {
00730 
00731          points = gnome_canvas_points_new(2);
00732          points->coords[0] = (double) x;
00733          points->coords[1] = (double) y;
00734          points->coords[2] = (double) x;
00735          points->coords[3] = (double) y + 1;
00736 
00737          item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(grid_root_item),
00738                                    gnome_canvas_line_get_type (),
00739                                    "points", points,
00740                                    "fill_color_rgba", GRID_COLOR,
00741                                    "width_pixels", 1,
00742                                    NULL);
00743 
00744          gtk_signal_connect(GTK_OBJECT(item), "event",
00745                           (GtkSignalFunc) item_event,
00746                           NULL);
00747 
00748          gnome_canvas_points_unref(points);
00749 
00750        }
00751     }
00752 }
00753 
00754 /*
00755  * Given a pair (x,y) rewrite them so that (x,y) is on a grid node
00756  * Do nothing if grid_step is 0
00757  */
00758 static void snap_to_grid(double *x, double *y)
00759 {
00760   guint tmp;
00761 
00762   if(grid_step==0)
00763     return;
00764 
00765   tmp = (guint)((*x+(grid_step/2)) - drawing_area_x1)/grid_step;
00766   *x = (double)drawing_area_x1 + tmp*grid_step;
00767 
00768   tmp = (guint)((*y+(grid_step/2)) - drawing_area_y1)/grid_step;
00769   *y = (double)drawing_area_y1 + tmp*grid_step;
00770 }
00771 
00772 /* Destroy all the items */
00773 static void draw_destroy_all_items()
00774 {
00775 
00776   /* Deleting the root item automatically deletes children items */
00777   if(shape_root_item!=NULL)
00778     gtk_object_destroy (GTK_OBJECT(shape_root_item));
00779 
00780   shape_root_item = NULL;
00781   grid_root_item = NULL;
00782   current_color_item = NULL;
00783 }
00784 
00785 /*
00786  * Return the proper GDK cursor based on the given tool
00787  *
00788  */
00789 static guint get_tool_cursor(ToolList tool)
00790 {
00791   switch(tool)
00792     {
00793     case TOOL_RECT:
00794       return(GCOMPRIS_FILLRECT_CURSOR);
00795       break;
00796     case TOOL_FILLED_RECT:
00797       return(GCOMPRIS_RECT_CURSOR);
00798       break;
00799     case TOOL_CIRCLE:
00800       return(GCOMPRIS_CIRCLE_CURSOR);
00801       break;
00802     case TOOL_FILLED_CIRCLE:
00803       return(GCOMPRIS_FILLCIRCLE_CURSOR);
00804       break;
00805     case TOOL_RAISE:
00806     case TOOL_LOWER:
00807     case TOOL_IMAGE:
00808     case TOOL_LINE:
00809     case TOOL_TEXT:
00810       return(GCOMPRIS_LINE_CURSOR);
00811       break;
00812     case TOOL_FILL:
00813       return(GCOMPRIS_FILL_CURSOR);
00814       break;
00815     case TOOL_DELETE:
00816       return(GCOMPRIS_DEL_CURSOR);
00817       break;
00818     case TOOL_SELECT:
00819       return(GCOMPRIS_SELECT_CURSOR);
00820       break;
00821     default:
00822       return(GCOMPRIS_DEFAULT_CURSOR);
00823       break;
00824     }
00825   return(0);
00826 }
00827 
00831 static void set_current_tool(GnomeCanvasItem *item, gint tool)
00832 {
00833   GdkPixbuf *pixmap = NULL;
00834 
00835   if(currentToolItem)
00836     {
00837       pixmap = gc_pixmap_load(tool_pixmap_name[(currentTool*2) + PIXMAP_OFF]);
00838       if(pixmap)
00839        {
00840          gnome_canvas_item_set (currentToolItem,
00841                              "pixbuf", pixmap,
00842                              NULL);
00843          gdk_pixbuf_unref(pixmap);
00844        }
00845     }
00846 
00847   currentTool = tool;
00848   currentToolItem = item;
00849 
00850   pixmap = gc_pixmap_load(tool_pixmap_name[(currentTool*2) + PIXMAP_ON]);
00851   if(pixmap)
00852     {
00853       gnome_canvas_item_set (item,
00854                           "pixbuf", pixmap,
00855                           NULL);
00856       gdk_pixbuf_unref(pixmap);
00857     }
00858 }
00859 
00863 static gint
00864 tool_event(GnomeCanvasItem *item, GdkEvent *event, gint tool)
00865 {
00866 
00867   if(!gcomprisBoard || board_paused)
00868     return FALSE;
00869 
00870   switch (event->type)
00871     {
00872     case GDK_BUTTON_PRESS:
00873       switch(event->button.button)
00874        {
00875        case 1:
00876 
00877          switch(tool)
00878            {
00879            case TOOL_LOAD:
00880              //            gc_selector_file_load(gcomprisBoard, FILE_SELECTOR_ROOT, "", load_drawing);
00881              break;
00882            case TOOL_SAVE:
00883              //            gc_selector_file_save(gcomprisBoard, FILE_SELECTOR_ROOT, "", save_drawing);
00884              break;
00885            case TOOL_GRID:
00886              display_grid((grid_step==0 ? TRUE : FALSE));
00887              return TRUE;
00888              break;
00889            case TOOL_IMAGE:
00890              gc_selector_images_start(gcomprisBoard, "dataset", image_selected);
00891              break;
00892            case TOOL_RAISE:
00893            case TOOL_LOWER:
00894              if(selected_anchors_item)
00895               display_anchors(selected_anchors_item, FALSE);
00896 
00897              selected_anchors_item = NULL;
00898              break;
00899            default:
00900              break;
00901            }
00902 
00903          set_current_tool(item, tool);
00904 
00905        default:
00906          break;
00907        }
00908     default:
00909       break;
00910     }
00911   return FALSE;
00912 }
00913 
00914 static void highlight_color_item(GnomeCanvasItem *item)
00915 {
00916   // Highligh the selected color
00917   if(current_color_item)
00918     gnome_canvas_item_set (current_color_item,
00919                         "outline_color_rgba", 0x07a3e080,
00920                         "width_pixels", 0,
00921                         NULL);
00922 
00923   gnome_canvas_item_set (item,
00924                       "outline_color_rgba", 0xaef45880,
00925                       "width_pixels", 3,
00926                       NULL);
00927   current_color_item=item;
00928 }
00929 
00930 static gint
00931 ext_color_event(GnomeCanvasItem *item, GdkEvent *event, gpointer color_rgba)
00932 {
00933   guint color = GPOINTER_TO_INT(color_rgba);
00934 
00935   if(!gcomprisBoard || board_paused)
00936     return FALSE;
00937 
00938   if(color_rgba==NULL)
00939     return FALSE;
00940 
00941   switch (event->type)
00942     {
00943     case GDK_BUTTON_PRESS:
00944       switch(event->button.button)
00945        {
00946        case 1:
00947          {
00948            currentColor = color;
00949            highlight_color_item(item);
00950          }
00951          break;
00952        default:
00953          break;
00954        }
00955     default:
00956       break;
00957     }
00958   return FALSE;
00959 }
00960 
00961 static void display_anchors(AnchorsItem *anchorsItem, gboolean visible)
00962 {
00963 
00964   g_assert(anchorsItem != NULL);
00965 
00966   if(visible)
00967     {
00968       if(anchorsItem->nw && GNOME_IS_CANVAS_RECT(anchorsItem->nw))
00969        {
00970          gnome_canvas_item_show(anchorsItem->nw);
00971          gnome_canvas_item_raise_to_top(anchorsItem->nw);
00972        }
00973 
00974       if(anchorsItem->n && GNOME_IS_CANVAS_RECT(anchorsItem->n))
00975        {
00976          gnome_canvas_item_show(anchorsItem->n);
00977          gnome_canvas_item_raise_to_top(anchorsItem->n);
00978        }
00979 
00980       if(anchorsItem->ne && GNOME_IS_CANVAS_RECT(anchorsItem->ne))
00981        {
00982          gnome_canvas_item_show(anchorsItem->ne);
00983          gnome_canvas_item_raise_to_top(anchorsItem->ne);
00984        }
00985 
00986       if(anchorsItem->w && GNOME_IS_CANVAS_RECT(anchorsItem->w))
00987        {
00988          gnome_canvas_item_show(anchorsItem->w);
00989          gnome_canvas_item_raise_to_top(anchorsItem->w);
00990        }
00991 
00992       if(anchorsItem->e && GNOME_IS_CANVAS_RECT(anchorsItem->e))
00993        {
00994          gnome_canvas_item_show(anchorsItem->e);
00995          gnome_canvas_item_raise_to_top(anchorsItem->e);
00996        }
00997 
00998       if(anchorsItem->sw && GNOME_IS_CANVAS_RECT(anchorsItem->sw))
00999        {
01000          gnome_canvas_item_show(anchorsItem->sw);
01001          gnome_canvas_item_raise_to_top(anchorsItem->sw);
01002        }
01003 
01004       if(anchorsItem->s && GNOME_IS_CANVAS_RECT(anchorsItem->s))
01005        {
01006          gnome_canvas_item_show(anchorsItem->s);
01007          gnome_canvas_item_raise_to_top(anchorsItem->s);
01008        }
01009 
01010       if(anchorsItem->se && GNOME_IS_CANVAS_RECT(anchorsItem->se))
01011        {
01012          gnome_canvas_item_show(anchorsItem->se);
01013          gnome_canvas_item_raise_to_top(anchorsItem->se);
01014        }
01015 
01016     }
01017   else
01018     {
01019       if(anchorsItem->nw && GNOME_IS_CANVAS_RECT(anchorsItem->nw))
01020        gnome_canvas_item_hide(anchorsItem->nw);
01021 
01022       if(anchorsItem->n && GNOME_IS_CANVAS_RECT(anchorsItem->n))
01023        gnome_canvas_item_hide(anchorsItem->n);
01024 
01025       if(anchorsItem->ne && GNOME_IS_CANVAS_RECT(anchorsItem->ne))
01026        gnome_canvas_item_hide(anchorsItem->ne);
01027 
01028       if(anchorsItem->w && GNOME_IS_CANVAS_RECT(anchorsItem->w))
01029        gnome_canvas_item_hide(anchorsItem->w);
01030 
01031       if(anchorsItem->e && GNOME_IS_CANVAS_RECT(anchorsItem->e))
01032        gnome_canvas_item_hide(anchorsItem->e);
01033 
01034       if(anchorsItem->sw && GNOME_IS_CANVAS_RECT(anchorsItem->sw))
01035        gnome_canvas_item_hide(anchorsItem->sw);
01036 
01037       if(anchorsItem->s && GNOME_IS_CANVAS_RECT(anchorsItem->s))
01038        gnome_canvas_item_hide(anchorsItem->s);
01039 
01040       if(anchorsItem->se && GNOME_IS_CANVAS_RECT(anchorsItem->se))
01041        gnome_canvas_item_hide(anchorsItem->se);
01042     }
01043 }
01044 
01045 static void reset_anchors_text(AnchorsItem *anchorsItem)
01046 {
01047 
01048   double x1, x2, y1, y2;
01049 
01050   gnome_canvas_item_get_bounds(anchorsItem->item,  &x1, &y1, &x2, &y2);
01051 
01052   if(anchorsItem->nw)
01053     gnome_canvas_item_set (anchorsItem->nw,
01054                         "x1", (double) x1+(x2-x1)/2 - DEFAULT_ANCHOR_SIZE,
01055                         "y1", (double) y2 - DEFAULT_ANCHOR_SIZE,
01056                         "x2", (double) x1+(x2-x1)/2 + DEFAULT_ANCHOR_SIZE,
01057                         "y2", (double) y2 + DEFAULT_ANCHOR_SIZE,
01058                         NULL);
01059 
01060 }
01061 
01062 static void reset_anchors_line(AnchorsItem *anchorsItem)
01063 {
01064   GnomeCanvasItem *item;
01065   double x1, x2, y1, y2;
01066   GnomeCanvasPoints *points;
01067 
01068   item = anchorsItem->item;
01069 
01070   g_object_get(G_OBJECT(item), "points", &points, NULL);
01071   if (points == NULL){
01072     g_warning ("ERROR: LINE points NULL\n");
01073     return;
01074   }
01075   x1 = points->coords[0];
01076   y1 = points->coords[1];
01077   x2 = points->coords[2];
01078   y2 = points->coords[3];
01079 
01080   if(anchorsItem->nw)
01081     gnome_canvas_item_set (anchorsItem->nw,
01082                         "x1", (double) x1 - DEFAULT_ANCHOR_SIZE,
01083                         "y1", (double) y1 - DEFAULT_ANCHOR_SIZE,
01084                         "x2", (double) x1 + DEFAULT_ANCHOR_SIZE,
01085                         "y2", (double) y1 + DEFAULT_ANCHOR_SIZE,
01086                         NULL);
01087 
01088   if(anchorsItem->se)
01089     gnome_canvas_item_set (anchorsItem->se,
01090                         "x1", (double) x2 - DEFAULT_ANCHOR_SIZE,
01091                         "y1", (double) y2 - DEFAULT_ANCHOR_SIZE,
01092                         "x2", (double) x2 + DEFAULT_ANCHOR_SIZE,
01093                         "y2", (double) y2 + DEFAULT_ANCHOR_SIZE,
01094                         NULL);
01095 
01096 }
01097 
01098 
01099 static void reset_anchors_bounded(AnchorsItem *anchorsItem)
01100 {
01101   GnomeCanvasItem *item;
01102   double x1, x2, y1, y2;
01103 
01104   item = anchorsItem->item;
01105 
01106   //gnome_canvas_item_get_bounds(item,  &x1, &y1, &x2, &y2);
01107 
01108   /* For each type of item, get the bounding box
01109    * We do not use gnome_canvas_item_get_bounds because it creates lags
01110    */
01111   if (G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_RECT || 
01112       G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_ELLIPSE) {
01113 
01114     g_object_get(G_OBJECT(item), "x1", &x1, "y1", &y1, "x2", &x2, "y2", &y2, NULL);
01115 
01116   } else if (G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_PIXBUF ) {
01117     double width, height;
01118 
01119     g_object_get(G_OBJECT(item), "x", &x1, "y", &y1, NULL);
01120     g_object_get(G_OBJECT(item), "width", &width, "height", &height, NULL);
01121     x2 = x1 + width;
01122     y2 = y1 + height;
01123   }
01124 
01125   if(anchorsItem->nw)
01126     gnome_canvas_item_set (anchorsItem->nw,
01127                         "x1", (double) x1 - DEFAULT_ANCHOR_SIZE,
01128                         "y1", (double) y1 - DEFAULT_ANCHOR_SIZE,
01129                         "x2", (double) x1 + DEFAULT_ANCHOR_SIZE,
01130                         "y2", (double) y1 + DEFAULT_ANCHOR_SIZE,
01131                         NULL);
01132 
01133   if(anchorsItem->n)
01134     gnome_canvas_item_set (anchorsItem->n,
01135                         "x1", (double) x1+(x2-x1)/2 - DEFAULT_ANCHOR_SIZE,
01136                         "y1", (double) y1 - DEFAULT_ANCHOR_SIZE,
01137                         "x2", (double) x1+(x2-x1)/2 + DEFAULT_ANCHOR_SIZE,
01138                         "y2", (double) y1 + DEFAULT_ANCHOR_SIZE,
01139                         NULL);
01140 
01141   if(anchorsItem->ne)
01142     gnome_canvas_item_set (anchorsItem->ne,
01143                         "x1", (double) x2 - DEFAULT_ANCHOR_SIZE,
01144                         "y1", (double) y1 - DEFAULT_ANCHOR_SIZE,
01145                         "x2", (double) x2 + DEFAULT_ANCHOR_SIZE,
01146                         "y2", (double) y1 + DEFAULT_ANCHOR_SIZE,
01147                         NULL);
01148 
01149   if(anchorsItem->e)
01150     gnome_canvas_item_set (anchorsItem->e,
01151                         "x1", (double) x2 - DEFAULT_ANCHOR_SIZE,
01152                         "y1", (double) y1+(y2-y1)/2 - DEFAULT_ANCHOR_SIZE,
01153                         "x2", (double) x2 + DEFAULT_ANCHOR_SIZE,
01154                         "y2", (double) y1+(y2-y1)/2 + DEFAULT_ANCHOR_SIZE,
01155                         NULL);
01156 
01157   if(anchorsItem->w)
01158     gnome_canvas_item_set (anchorsItem->w,
01159                         "x1", (double) x1 - DEFAULT_ANCHOR_SIZE,
01160                         "y1", (double) y1+(y2-y1)/2 - DEFAULT_ANCHOR_SIZE,
01161                         "x2", (double) x1 + DEFAULT_ANCHOR_SIZE,
01162                         "y2", (double) y1+(y2-y1)/2 + DEFAULT_ANCHOR_SIZE,
01163                         NULL);
01164 
01165   if(anchorsItem->sw)
01166     gnome_canvas_item_set (anchorsItem->sw,
01167                         "x1", (double) x1 - DEFAULT_ANCHOR_SIZE,
01168                         "y1", (double) y2 - DEFAULT_ANCHOR_SIZE,
01169                         "x2", (double) x1 + DEFAULT_ANCHOR_SIZE,
01170                         "y2", (double) y2 + DEFAULT_ANCHOR_SIZE,
01171                         NULL);
01172 
01173   if(anchorsItem->se)
01174     gnome_canvas_item_set (anchorsItem->se,
01175                         "x1", (double) x2 - DEFAULT_ANCHOR_SIZE,
01176                         "y1", (double) y2 - DEFAULT_ANCHOR_SIZE,
01177                         "x2", (double) x2 + DEFAULT_ANCHOR_SIZE,
01178                         "y2", (double) y2 + DEFAULT_ANCHOR_SIZE,
01179                         NULL);
01180 
01181   if(anchorsItem->s)
01182     gnome_canvas_item_set (anchorsItem->s,
01183                         "x1", (double) x1+(x2-x1)/2 - DEFAULT_ANCHOR_SIZE,
01184                         "y1", (double) y2 - DEFAULT_ANCHOR_SIZE,
01185                         "x2", (double) x1+(x2-x1)/2 + DEFAULT_ANCHOR_SIZE,
01186                         "y2", (double) y2 + DEFAULT_ANCHOR_SIZE,
01187                         NULL);
01188 
01189 }
01190 
01191 static void resize_item(AnchorsItem *anchorsItem, AnchorType anchor, double x, double y)
01192 {
01193   double              x1, y1, x2, y2;
01194   GnomeCanvasPoints  *points = NULL;
01195   GnomeCanvasItem    *item = NULL;
01196 
01197   item = anchorsItem->item;
01198   gnome_canvas_item_get_bounds  (item,
01199                              &x1,
01200                              &y1,
01201                              &x2,
01202                              &y2);
01203 
01204   if(GNOME_IS_CANVAS_PIXBUF(item))
01205     {
01206       switch(anchor)
01207        {
01208        case ANCHOR_E:
01209          if(x>x1+1)
01210            gnome_canvas_item_set (item,
01211                                "width", (double) x-x1,
01212                                NULL);
01213          break;
01214        case ANCHOR_W:
01215          if(x<x2-1)
01216            {
01217              gnome_canvas_item_set (item,
01218                                  "x", (double) x,
01219                                  NULL);
01220              gnome_canvas_item_set (item,
01221                                  "width", (double) x2-x,
01222                                  NULL);
01223            }
01224          break;
01225        case ANCHOR_N:
01226          if(y<y2-1)
01227            {
01228              gnome_canvas_item_set (item,
01229                                  "y", (double) y,
01230                                  NULL);
01231              gnome_canvas_item_set (item,
01232                                  "height", (double) y2-y,
01233                                  NULL);
01234            }
01235          break;
01236        case ANCHOR_S:
01237          if(y>y1+1)
01238            gnome_canvas_item_set (item,
01239                                "height", (double) y-y1,
01240                                NULL);
01241          break;
01242        case ANCHOR_NW:
01243          if(y<y2-1)
01244            {
01245              gnome_canvas_item_set (item,
01246                                  "y", (double) y,
01247                                  NULL);
01248              gnome_canvas_item_set (item,
01249                                  "height", (double) y2-y,
01250                                  NULL);
01251            }
01252          if(x<x2-1)
01253            {
01254              gnome_canvas_item_set (item,
01255                                  "x", (double) x,
01256                                  NULL);
01257              gnome_canvas_item_set (item,
01258                                  "width", (double) x2-x,
01259                                  NULL);
01260            }
01261          break;
01262        case ANCHOR_NE:
01263          if(y<y2-1)
01264            {
01265              gnome_canvas_item_set (item,
01266                                  "y", (double) y,
01267                                  NULL);
01268              gnome_canvas_item_set (item,
01269                                  "height", (double) y2-y,
01270                                  NULL);
01271            }
01272          if(x>x1+1)
01273            {
01274              gnome_canvas_item_set (item,
01275                                  "width", (double) x,
01276                                  NULL);
01277              gnome_canvas_item_set (item,
01278                                  "width", (double) x-x1,
01279                                  NULL);
01280            }
01281          break;
01282        case ANCHOR_SW:
01283          if(y>y1+1)
01284            {
01285              gnome_canvas_item_set (item,
01286                                  "height", (double) y,
01287                                  NULL);
01288            gnome_canvas_item_set (item,
01289                                "height", (double) y-y1,
01290                                NULL);
01291            }
01292          if(x<x2-1)
01293            {
01294              gnome_canvas_item_set (item,
01295                                  "x", (double) x,
01296                                  NULL);
01297              gnome_canvas_item_set (item,
01298                                  "width", (double) x2-x,
01299                                  NULL);
01300            }
01301          break;
01302        case ANCHOR_SE:
01303          if(y>y1+1)
01304            {
01305              gnome_canvas_item_set (item,
01306                                  "height", (double) y,
01307                                  NULL);
01308              gnome_canvas_item_set (item,
01309                                  "height", (double) y-y1,
01310                                  NULL);
01311            }
01312          if(x>x1+1)
01313            {
01314              gnome_canvas_item_set (item,
01315                                  "width", (double) x,
01316                                  NULL);
01317              gnome_canvas_item_set (item,
01318                                  "width", (double) x-x1,
01319                                  NULL);
01320            }
01321          break;
01322        }
01323 
01324       reset_anchors_bounded(anchorsItem);
01325     }
01326   else if(GNOME_IS_CANVAS_RECT(item) || GNOME_IS_CANVAS_ELLIPSE(item))
01327     {
01328       switch(anchor)
01329        {
01330        case ANCHOR_E:
01331          if(x>x1+1)
01332            gnome_canvas_item_set (item,
01333                                "x2", (double) x,
01334                                NULL);
01335          break;
01336        case ANCHOR_W:
01337          if(x<x2-1)
01338            gnome_canvas_item_set (item,
01339                                "x1", (double) x,
01340                                NULL);
01341          break;
01342        case ANCHOR_N:
01343          if(y<y2-1)
01344            gnome_canvas_item_set (item,
01345                                "y1", (double) y,
01346                                NULL);
01347          break;
01348        case ANCHOR_S:
01349          if(y>y1+1)
01350            gnome_canvas_item_set (item,
01351                                "y2", (double) y,
01352                                NULL);
01353          break;
01354        case ANCHOR_NW:
01355          if(y<y2-1)
01356            gnome_canvas_item_set (item,
01357                                "y1", (double) y,
01358                                NULL);
01359          if(x<x2-1)
01360            gnome_canvas_item_set (item,
01361                                "x1", (double) x,
01362                                NULL);
01363          break;
01364        case ANCHOR_NE:
01365          if(y<y2-1)
01366            gnome_canvas_item_set (item,
01367                                "y1", (double) y,
01368                                NULL);
01369          if(x>x1+1)
01370            gnome_canvas_item_set (item,
01371                                "x2", (double) x,
01372                                NULL);
01373          break;
01374        case ANCHOR_SW:
01375          if(y>y1+1)
01376            gnome_canvas_item_set (item,
01377                                "y2", (double) y,
01378                                NULL);
01379          if(x<x2-1)
01380            gnome_canvas_item_set (item,
01381                                "x1", (double) x,
01382                                NULL);
01383          break;
01384        case ANCHOR_SE:
01385          if(y>y1+1)
01386            gnome_canvas_item_set (item,
01387                                "y2", (double) y,
01388                                NULL);
01389          if(x>x1+1)
01390            gnome_canvas_item_set (item,
01391                                "x2", (double) x,
01392                                NULL);
01393          break;
01394        }
01395 
01396       reset_anchors_bounded(anchorsItem);
01397     }
01398   else if(GNOME_IS_CANVAS_LINE(item))
01399     {
01400 
01401       /* I don't know why, I need to shrink the bounding box */
01402       x1 += DRAW_WIDTH_PIXELS;
01403       y1 += DRAW_WIDTH_PIXELS;
01404       x2 -= DRAW_WIDTH_PIXELS;
01405       y2 -= DRAW_WIDTH_PIXELS;
01406 
01407       switch(anchor)
01408        {
01409        case ANCHOR_NW:
01410          points = gnome_canvas_points_new(2);
01411          points->coords[0] = (double) x;
01412          points->coords[1] = (double) y;
01413          points->coords[2] = (double) anchorsItem->ref_x2;
01414          points->coords[3] = (double) anchorsItem->ref_y2;
01415          break;
01416        case ANCHOR_SE:
01417          points = gnome_canvas_points_new(2);
01418          points->coords[0] = (double) anchorsItem->ref_x1;
01419          points->coords[1] = (double) anchorsItem->ref_y1;
01420          points->coords[2] = (double) x;
01421          points->coords[3] = (double) y;
01422          break;
01423        default:
01424          break;
01425        }
01426 
01427       if(points)
01428        {
01429          anchorsItem->ref_x1 = points->coords[0];
01430          anchorsItem->ref_y1 = points->coords[1];
01431          anchorsItem->ref_x2 = points->coords[2];
01432          anchorsItem->ref_y2 = points->coords[3];
01433 
01434          gnome_canvas_item_set (item,
01435                              "points", points,
01436                              NULL);
01437 
01438          gnome_canvas_points_unref(points);
01439 
01440          reset_anchors_line(anchorsItem);
01441        }
01442     }
01443   else if(GNOME_IS_CANVAS_TEXT(item))
01444     {
01445       /* FIXME : Should take care of not moving the text outside the drawing area */
01446       /* Resizing a text is just moving it */
01447       gnome_canvas_item_set (item,
01448                           "y", (double) y,
01449                           "x", (double) x,
01450                           NULL);
01451       reset_anchors_text(anchorsItem);
01452     }
01453 }
01454 
01455 /*
01456  * Set the color of the item based on the tool with which it has been
01457  * created
01458  *
01459  */
01460 static void set_item_color(AnchorsItem *anchorsItem, guint color)
01461 {
01462   GnomeCanvasItem *item = anchorsItem->item;
01463 
01464   switch(anchorsItem->tool)
01465     {
01466     case TOOL_RECT:
01467     case TOOL_CIRCLE:
01468       gnome_canvas_item_set (GNOME_CANVAS_ITEM(item),
01469                           "outline_color_rgba", color,
01470                           NULL);
01471       break;
01472     case TOOL_FILLED_RECT:
01473     case TOOL_FILLED_CIRCLE:
01474     case TOOL_TEXT:
01475       gnome_canvas_item_set (GNOME_CANVAS_ITEM(item),
01476                           "fill_color_rgba", color,
01477                           NULL);
01478       break;
01479     case TOOL_LINE:
01480       gnome_canvas_item_set (GNOME_CANVAS_ITEM(item),
01481                           "fill_color_rgba", color,
01482                           NULL);
01483       break;
01484     default:
01485       break;
01486     }
01487 }
01488 
01489 /*
01490  * Given an item, return the tool as a ToolList used to create it
01491  *
01492  */
01493 static ToolList get_tool(GnomeCanvasItem *item)
01494 {
01495   if (G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_GROUP )
01496     return -1;
01497   else if (G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_RECT )
01498     return TOOL_RECT;
01499   else if (G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_ELLIPSE )
01500     return TOOL_CIRCLE;
01501   else if (G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_LINE )
01502     return TOOL_LINE;
01503   else if (G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_TEXT )
01504     return TOOL_TEXT;
01505   else if (G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_PIXBUF )
01506     return TOOL_IMAGE;
01507 
01508   return -1;
01509 }
01510 
01511 /*
01512  * Create the anchors
01513  * (The item MUST BE in a group. The anchors are created in this group also)
01514  */
01515 static void create_anchors(GnomeCanvasItem *item)
01516 {
01517   GnomeCanvasGroup   *item_root_item = NULL;
01518   GnomeCanvasItem    *anchorItem = NULL;
01519   AnchorsItem        *anchorsItem = NULL;
01520   ToolList            currentTool;
01521 
01522   g_assert(item != NULL);
01523 
01524   item_root_item = GNOME_CANVAS_GROUP(item->parent);
01525 
01526   /* Let the new item be on top */
01527   gnome_canvas_item_raise_to_top(item);
01528 
01529   currentTool = get_tool(item);
01530 
01531   /* Create the Anchors */
01532   anchorsItem = g_new0(AnchorsItem, 1);
01533 
01534   anchorsItem->rootitem = GNOME_CANVAS_ITEM(item_root_item);
01535   anchorsItem->item = item;
01536   anchorsItem->tool = currentTool;
01537 
01538 
01539   /*----------------------------------------*/
01540   switch(currentTool)
01541     {
01542     case TOOL_LINE:
01543       {
01544        GnomeCanvasPoints* points = NULL;
01545 
01546        // Keep track of the original size. It helps the resize operation for the line
01547        g_object_get(G_OBJECT(item), "points", &points, NULL);
01548        if (points == NULL){
01549          g_warning ("ERROR: LINE points NULL \n");
01550          return;
01551        } else {
01552          anchorsItem->ref_x1 = points->coords[0];
01553          anchorsItem->ref_y1 = points->coords[1];
01554          anchorsItem->ref_x2 = points->coords[2];
01555          anchorsItem->ref_y2 = points->coords[3];
01556        }
01557 
01558        anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01559                                        gnome_canvas_rect_get_type (),
01560                                        "fill_color_rgba", ANCHOR_COLOR,
01561                                        "outline_color", "black",
01562                                        "width_pixels", 1,
01563                                        NULL);
01564        anchorsItem->nw = anchorItem;
01565        gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_NW);
01566        gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01567        
01568        gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01569                       (GtkSignalFunc) item_event_resize,
01570                       anchorsItem);
01571 
01572        /*----------------------------------------*/
01573        anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01574                                        gnome_canvas_rect_get_type (),
01575                                        "fill_color_rgba", ANCHOR_COLOR,
01576                                        "outline_color", "black",
01577                                        "width_pixels", 1,
01578                                        NULL);
01579        anchorsItem->se = anchorItem;
01580        gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_SE);
01581        gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01582 
01583        gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01584                         (GtkSignalFunc) item_event_resize,
01585                         anchorsItem);
01586 
01587        anchorsItem->n  = NULL;
01588        anchorsItem->s  = NULL;
01589        anchorsItem->e  = NULL;
01590        anchorsItem->w  = NULL;
01591        anchorsItem->ne = NULL;
01592        anchorsItem->sw = NULL;
01593 
01594        reset_anchors_line(anchorsItem);
01595        break;
01596       }
01597     case TOOL_IMAGE:
01598     case TOOL_RECT:
01599     case TOOL_CIRCLE:
01600     case TOOL_FILLED_RECT:
01601     case TOOL_FILLED_CIRCLE:
01602       anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01603                                      gnome_canvas_rect_get_type (),
01604                                      "fill_color_rgba", ANCHOR_COLOR,
01605                                      "outline_color", "black",
01606                                      "width_pixels", 1,
01607                                      NULL);
01608       anchorsItem->nw = anchorItem;
01609       gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_NW);
01610       gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01611 
01612       gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01613                       (GtkSignalFunc) item_event_resize,
01614                       anchorsItem);
01615 
01616       /*----------------------------------------*/
01617       anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01618                                      gnome_canvas_rect_get_type (),
01619                                      "fill_color_rgba", ANCHOR_COLOR,
01620                                      "outline_color", "black",
01621                                      "width_pixels", 1,
01622                                      NULL);
01623       anchorsItem->n = anchorItem;
01624       gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_N);
01625       gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01626 
01627       gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01628                       (GtkSignalFunc) item_event_resize,
01629                       anchorsItem);
01630 
01631       /*----------------------------------------*/
01632       anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01633                                      gnome_canvas_rect_get_type (),
01634                                      "fill_color_rgba", ANCHOR_COLOR,
01635                                      "outline_color", "black",
01636                                      "width_pixels", 1,
01637                                      NULL);
01638       anchorsItem->ne = anchorItem;
01639       gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_NE);
01640       gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01641 
01642       gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01643                       (GtkSignalFunc) item_event_resize,
01644                       anchorsItem);
01645 
01646       /*----------------------------------------*/
01647       anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01648                                      gnome_canvas_rect_get_type (),
01649                                      "fill_color_rgba", ANCHOR_COLOR,
01650                                      "outline_color", "black",
01651                                      "width_pixels", 1,
01652                                      NULL);
01653       anchorsItem->sw = anchorItem;
01654       gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_SW);
01655       gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01656 
01657       gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01658                       (GtkSignalFunc) item_event_resize,
01659                       anchorsItem);
01660 
01661       /*----------------------------------------*/
01662       anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01663                                      gnome_canvas_rect_get_type (),
01664                                      "fill_color_rgba", ANCHOR_COLOR,
01665                                      "outline_color", "black",
01666                                      "width_pixels", 1,
01667                                      NULL);
01668       anchorsItem->s = anchorItem;
01669       gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_S);
01670       gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01671 
01672       gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01673                       (GtkSignalFunc) item_event_resize,
01674                       anchorsItem);
01675 
01676       /*----------------------------------------*/
01677       anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01678                                      gnome_canvas_rect_get_type (),
01679                                      "fill_color_rgba", ANCHOR_COLOR,
01680                                      "outline_color", "black",
01681                                      "width_pixels", 1,
01682                                      NULL);
01683       anchorsItem->se = anchorItem;
01684       gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_SE);
01685       gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01686 
01687       gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01688                       (GtkSignalFunc) item_event_resize,
01689                       anchorsItem);
01690 
01691       /*----------------------------------------*/
01692       anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01693                                      gnome_canvas_rect_get_type (),
01694                                      "fill_color_rgba", ANCHOR_COLOR,
01695                                      "outline_color", "black",
01696                                      "width_pixels", 1,
01697                                      NULL);
01698       anchorsItem->w = anchorItem;
01699       gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_W);
01700       gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01701 
01702       gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01703                       (GtkSignalFunc) item_event_resize,
01704                       anchorsItem);
01705 
01706       /*----------------------------------------*/
01707       anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01708                                      gnome_canvas_rect_get_type (),
01709                                      "fill_color_rgba", ANCHOR_COLOR,
01710                                      "outline_color", "black",
01711                                      "width_pixels", 1,
01712                                      NULL);
01713       anchorsItem->e = anchorItem;
01714       gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_E);
01715       gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01716 
01717       gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01718                       (GtkSignalFunc) item_event_resize,
01719                       anchorsItem);
01720 
01721       reset_anchors_bounded(anchorsItem);
01722       break;
01723 
01724       /* Anchors is needed to show the text widget that has the focus */
01725     case TOOL_TEXT:
01726       anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01727                                      gnome_canvas_rect_get_type (),
01728                                      "fill_color_rgba", ANCHOR_COLOR,
01729                                      "outline_color", "black",
01730                                      "width_pixels", 1,
01731                                      NULL);
01732       anchorsItem->nw = anchorItem;
01733       gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_NW);
01734       gtk_object_set_data(GTK_OBJECT(anchorItem),"anchors", GINT_TO_POINTER(TRUE));
01735 
01736       gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
01737                       (GtkSignalFunc) item_event_resize,
01738                       anchorsItem);
01739 
01740       anchorsItem->n  = NULL;
01741       anchorsItem->s  = NULL;
01742       anchorsItem->e  = NULL;
01743       anchorsItem->w  = NULL;
01744       anchorsItem->ne = NULL;
01745       anchorsItem->se = NULL;
01746       anchorsItem->sw = NULL;
01747 
01748       reset_anchors_text(anchorsItem);
01749       break;
01750 
01751     default:
01752       /* No anchors in these cases */
01753       anchorsItem->n  = NULL;
01754       anchorsItem->s  = NULL;
01755       anchorsItem->e  = NULL;
01756       anchorsItem->w  = NULL;
01757       anchorsItem->ne = NULL;
01758       anchorsItem->sw = NULL;
01759       anchorsItem->nw = NULL;
01760       anchorsItem->se = NULL;
01761       break;
01762     }
01763 
01764   if(selected_anchors_item)
01765     display_anchors(selected_anchors_item, FALSE);
01766 
01767   selected_anchors_item = anchorsItem;
01768   display_anchors(anchorsItem, TRUE);
01769 
01770   /* Move is performed on the item itself */
01771   gtk_signal_connect(GTK_OBJECT(anchorsItem->rootitem), "event",
01772                    (GtkSignalFunc) item_event_move,
01773                    anchorsItem);
01774 }
01775 
01776 static GnomeCanvasItem *create_item(double x, double y, gchar *imagename)
01777 {
01778   GnomeCanvasItem *item = NULL;
01779   GnomeCanvasPoints* points = NULL;
01780   GnomeCanvasItem *item_root_item = NULL;
01781   guint item_size_x = 0;
01782   guint item_size_y = 0;
01783   GdkPixbuf *pixmap = NULL;
01784 
01785   item_root_item = \
01786     gnome_canvas_item_new (GNOME_CANVAS_GROUP(draw_root_item),
01787                         gnome_canvas_group_get_type (),
01788                         "x", (double)0,
01789                         "y", (double)0,
01790                         NULL);
01791 
01792   item_size_x = MIN(DEFAULT_ITEM_SIZE, drawing_area_x2 - x);
01793   item_size_y = MIN(DEFAULT_ITEM_SIZE, drawing_area_y2 - y);
01794 
01795   switch(currentTool)
01796     {
01797     case TOOL_IMAGE:
01798       // This is an image
01799       x = (drawing_area_x2-drawing_area_x1)/2;
01800       y = (drawing_area_y2-drawing_area_y1)/2;
01801       pixmap = gc_pixmap_load(imagename);
01802       item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01803                                 gnome_canvas_pixbuf_get_type (),
01804                                 "pixbuf", pixmap,
01805                                 "x", (double)x-gdk_pixbuf_get_width(pixmap)/2,
01806                                 "y", (double)y-gdk_pixbuf_get_height(pixmap)/2,
01807                                 "width", (double) gdk_pixbuf_get_width(pixmap),
01808                                 "height", (double) gdk_pixbuf_get_height(pixmap),
01809                                 "width_set", TRUE,
01810                                 "height_set", TRUE,
01811                             NULL);
01812       //                               "anchor", GTK_ANCHOR_CENTER,
01813 
01814       /* Tell svg_save the filename */
01815       gtk_object_set_data(GTK_OBJECT(item), "filename", g_strdup(imagename));
01816 
01817       gdk_pixbuf_unref(pixmap);
01818       break;
01819     case TOOL_RECT:
01820       // This is a rectangle
01821       item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01822                                 gnome_canvas_rect_get_type (),
01823                                 "x1", (double) x,
01824                                 "y1", (double) y,
01825                                 "x2", (double) x + item_size_x,
01826                                 "y2", (double) y + item_size_y,
01827                                 "outline_color_rgba", currentColor,
01828                                 "width_pixels", DRAW_WIDTH_PIXELS,
01829                                 NULL);
01830       /* Tell svg_save this is a transparent item */
01831       gtk_object_set_data(GTK_OBJECT(item),"empty", GINT_TO_POINTER(TRUE));
01832       break;
01833     case TOOL_FILLED_RECT:
01834       // This is a filled rectangle
01835       item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01836                                 gnome_canvas_rect_get_type (),
01837                                 "x1", (double) x,
01838                                 "y1", (double) y,
01839                                 "x2", (double) x + item_size_x,
01840                                 "y2", (double) y + item_size_y,
01841                                 "fill_color_rgba", currentColor,
01842                                 NULL);
01843       break;
01844     case TOOL_CIRCLE:
01845       // This is an ellipse
01846       item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01847                                 gnome_canvas_ellipse_get_type (),
01848                                 "x1", (double) x,
01849                                 "y1", (double) y,
01850                                 "x2", (double) x + item_size_x,
01851                                 "y2", (double) y + item_size_y,
01852                                 "outline_color_rgba", currentColor,
01853                                 "width_pixels", DRAW_WIDTH_PIXELS,
01854                                 NULL);
01855       /* Tell svg_save this is a transparent item */
01856       gtk_object_set_data(GTK_OBJECT(item),"empty", GINT_TO_POINTER(TRUE));
01857       break;
01858     case TOOL_FILLED_CIRCLE:
01859       // This is a filled ellipse
01860       item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01861                                 gnome_canvas_ellipse_get_type (),
01862                                 "x1", (double) x,
01863                                 "y1", (double) y,
01864                                 "x2", (double) x + item_size_x,
01865                                 "y2", (double) y + item_size_y,
01866                                 "fill_color_rgba", currentColor,
01867                                 NULL);
01868       break;
01869     case TOOL_LINE:
01870       // This is a line
01871       points = gnome_canvas_points_new(2);
01872       points->coords[0] = (double) x;
01873       points->coords[1] = (double) y;
01874       points->coords[2] = (double) x + item_size_x;
01875       points->coords[3] = (double) y + item_size_y;
01876 
01877       snap_to_grid(&points->coords[0], &points->coords[1]);
01878       snap_to_grid(&points->coords[2], &points->coords[3]);
01879 
01880       item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01881                                 gnome_canvas_line_get_type (),
01882                                 "points", points,
01883                                 "fill_color_rgba", currentColor,
01884                                 "width_pixels", DRAW_WIDTH_PIXELS,
01885                                 NULL);
01886       break;
01887     case TOOL_TEXT:
01888       // This is text
01889       {
01890        item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
01891                                   gnome_canvas_text_get_type (),
01892                                   "text", "?",
01893                                   "font", gc_skin_font_board_big_bold,
01894                                   "x", (double) x,
01895                                   "y", (double) y,
01896                                   "anchor", GTK_ANCHOR_CENTER,
01897                                   "fill_color_rgba", currentColor,
01898                                   NULL);
01899       }
01900       break;
01901     default:
01902       break;
01903     }
01904 
01905   /*
01906    * Create the anchors now
01907    */
01908   if(item)
01909     {
01910       create_anchors(item);
01911     }
01912 
01913   return item;
01914 }
01915 
01916 /*
01917  * Return the proper GDK cursor based on the given anchor
01918  *
01919  */
01920 static guint get_resize_cursor(AnchorType anchor)
01921 {
01922   switch(anchor)
01923     {
01924     case  ANCHOR_NW:
01925       return(GDK_TOP_LEFT_CORNER);
01926       break;
01927     case  ANCHOR_N:
01928       return(GDK_TOP_SIDE);
01929       break;
01930     case  ANCHOR_NE:
01931       return(GDK_TOP_RIGHT_CORNER);
01932       break;
01933     case  ANCHOR_E:
01934       return(GDK_RIGHT_SIDE);
01935       break;
01936     case  ANCHOR_W:
01937       return(GDK_LEFT_SIDE);
01938       break;
01939     case  ANCHOR_SW:
01940       return(GDK_BOTTOM_LEFT_CORNER);
01941       break;
01942     case  ANCHOR_S:
01943       return(GDK_BOTTOM_SIDE);
01944       break;
01945     case  ANCHOR_SE:
01946       return(GDK_BOTTOM_RIGHT_CORNER);
01947       break;
01948     }
01949 
01950   return 0;
01951 }
01952 
01953 /*
01954  * Special event callback for the resize operation
01955  */
01956 static gint
01957 item_event_resize(GnomeCanvasItem *item, GdkEvent *event, AnchorsItem *anchorsItem)
01958 {
01959   static double                     x, y;
01960   static GnomeCanvasItem    *draggingItem = NULL;
01961   static int                 dragging;
01962   double                     item_x, item_y;
01963   GdkCursor                 *fleur = NULL;
01964   AnchorType                 anchor;
01965 
01966   if(!gcomprisBoard || board_paused)
01967     return FALSE;
01968 
01969   anchor = (AnchorType)gtk_object_get_user_data(GTK_OBJECT(item));
01970 
01971   switch (event->type)
01972     {
01973     case GDK_BUTTON_PRESS:
01974       switch(event->button.button)
01975        {
01976        case 1:
01977          fleur = gdk_cursor_new(get_resize_cursor(anchor));
01978          
01979          gc_canvas_item_grab(item,
01980                              GDK_POINTER_MOTION_MASK |
01981                              GDK_BUTTON_RELEASE_MASK,
01982                              fleur,
01983                              event->button.time);
01984          gdk_cursor_destroy(fleur);
01985          draggingItem = item;
01986          dragging = TRUE;
01987 
01988          item_x = event->button.x;
01989          item_y = event->button.y;
01990          gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
01991          snap_to_grid(&item_x, &item_y);
01992          x = item_x;
01993          y = item_y;
01994          break;
01995        default:
01996          break;
01997        }
01998       break;
01999     case GDK_BUTTON_RELEASE:
02000       if(dragging)
02001        {
02002          gc_canvas_item_ungrab(item, event->button.time);
02003          dragging = FALSE;
02004          draggingItem = NULL;
02005        }
02006       break;
02007     case GDK_ENTER_NOTIFY:
02008       gc_cursor_set(get_resize_cursor(anchor));
02009       break;
02010 
02011     case GDK_LEAVE_NOTIFY:
02012       gc_cursor_set(get_tool_cursor(currentTool));
02013       break;
02014 
02015     case GDK_MOTION_NOTIFY:
02016       if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
02017        {
02018          double parent_x, parent_y;
02019 
02020          item_x = event->button.x;
02021          item_y = event->button.y;
02022          gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
02023 
02024          parent_x = event->button.x;
02025          parent_y = event->button.y;
02026          gnome_canvas_item_w2i(anchorsItem->rootitem->parent, &parent_x, &parent_y);
02027 
02028          snap_to_grid(&x, &y);
02029          resize_item(anchorsItem, anchor, x, y);
02030 
02031          /* Manage border limits */
02032          if((parent_x > drawing_area_x1) && (parent_x < drawing_area_x2))
02033            x = item_x;
02034 
02035          if((parent_y > drawing_area_y1) && (parent_y < drawing_area_y2))
02036            y = item_y;
02037 
02038        }
02039       break;
02040     default:
02041       break;
02042     }
02043 
02044   return(TRUE);
02045 }
02046 
02050 static void set_selected_item(AnchorsItem *anchorsItem)
02051 {
02052   if(selected_anchors_item!=anchorsItem)
02053     {
02054       if(selected_anchors_item)
02055        display_anchors(selected_anchors_item, FALSE);
02056 
02057       if(anchorsItem!=NULL)
02058        display_anchors(anchorsItem, TRUE);
02059 
02060       selected_anchors_item = anchorsItem;
02061     }
02062 }
02063 
02067 static void image_selected(gchar *image)
02068 {
02069   GnomeCanvasItem *item = NULL;
02070   item = create_item(clicked_x, clicked_y, image);
02071   set_current_tool(selectionToolItem, TOOL_SELECT);
02072 }
02073 
02074 /*
02075  * Recreate an item after it has been saved and is being reloaded
02076  *
02077  */
02078 static void recreate_item(GnomeCanvasItem *item)
02079 {
02080 
02081   if(item == NULL) 
02082     return;
02083 
02084   if (G_OBJECT_TYPE(item) == GNOME_TYPE_CANVAS_GROUP ) {
02085     /* If it's a group, then the first object is the real object to create the anchor for */
02086     recreate_item(GNOME_CANVAS_ITEM(g_list_nth_data(GNOME_CANVAS_GROUP(item)->item_list, 0)));
02087     return;
02088   }
02089 
02090   /* Rebuild the anchors */
02091   create_anchors(item);
02092 }
02093 
02097 static void load_drawing(gchar *file, gchar *type)
02098 {
02099 
02100 }
02101 
02105 static void save_drawing(gchar *file, gchar *type)
02106 {
02107 
02108 }
02109 
02110 /*
02111  * Special event callback for the move operation
02112  */
02113 static gint
02114 item_event_move(GnomeCanvasItem *item, GdkEvent *event, AnchorsItem *anchorsItem)
02115 {
02116   static double x, y;
02117   static double start_x, start_y;
02118   static GnomeCanvasItem *draggingItem = NULL;
02119   static int dragging;
02120   double new_x, new_y;
02121   double item_x, item_y;
02122   GdkCursor *fleur = NULL;
02123 
02124   if(!gcomprisBoard || board_paused)
02125     return FALSE;
02126 
02127   switch (event->type)
02128     {
02129     case GDK_BUTTON_PRESS:
02130       switch(event->button.button)
02131        {
02132        case 1:
02133          switch(currentTool) {
02134          case TOOL_IMAGE:
02135          case TOOL_RECT:
02136          case TOOL_FILLED_RECT:
02137          case TOOL_CIRCLE:
02138          case TOOL_FILLED_CIRCLE:
02139          case TOOL_LINE:
02140          case TOOL_TEXT:
02141            /* In this case, we simply redirect to the item creation */
02142            item_event(item, event, NULL);
02143            break;
02144          case TOOL_SELECT:
02145            // Move an item
02146            set_selected_item(anchorsItem);
02147 
02148            fleur = gdk_cursor_new(GDK_FLEUR);
02149 
02150            gc_canvas_item_grab(item,
02151                                GDK_POINTER_MOTION_MASK |
02152                                GDK_BUTTON_RELEASE_MASK,
02153                                fleur,
02154                                event->button.time);
02155            gdk_cursor_destroy(fleur);
02156            draggingItem = item;
02157            dragging = TRUE;
02158 
02159            item_x = event->button.x;
02160            item_y = event->button.y;
02161            gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
02162            snap_to_grid(&item_x, &item_y);
02163 
02164            x = item_x;
02165            y = item_y;
02166            start_x = item_x;
02167            start_y = item_y;
02168 
02169            display_anchors(anchorsItem, FALSE);
02170            break;
02171 
02172          case TOOL_DELETE:
02173            if(selected_anchors_item == anchorsItem)
02174              selected_anchors_item = NULL;
02175 
02176            gtk_object_destroy (GTK_OBJECT(anchorsItem->rootitem));
02177            g_free(anchorsItem);
02178            return FALSE;
02179            break;
02180 
02181          case TOOL_FILL:
02182            set_item_color(anchorsItem, currentColor);
02183            break;
02184 
02185          case TOOL_RAISE:
02186            gnome_canvas_item_raise(anchorsItem->rootitem, 1);
02187            break;
02188 
02189          case TOOL_LOWER:
02190            gnome_canvas_item_lower(anchorsItem->rootitem, 1);
02191            break;
02192 
02193          case TOOL_ROTATE_CW:
02194            gc_item_rotate_relative(anchorsItem->rootitem, 10);
02195            reset_anchors_bounded(anchorsItem);
02196            break;
02197 
02198          case TOOL_ROTATE_CCW:
02199            gc_item_rotate_relative(anchorsItem->rootitem, -10);
02200            reset_anchors_bounded(anchorsItem);
02201            break;
02202 
02203          case TOOL_FLIP:
02204            {
02205              GdkPixbuf *pixbuf;
02206              /* Only implemented for images */
02207              if(anchorsItem->tool == TOOL_IMAGE) {
02208               gtk_object_get (GTK_OBJECT (anchorsItem->item), "pixbuf", &pixbuf, NULL);
02209               if(pixbuf) {
02210                 GdkPixbuf *pixbuf2;
02211                 pixbuf2 = (GdkPixbuf *)pixbuf_copy_mirror(pixbuf, TRUE, FALSE);
02212                 gdk_pixbuf_unref(pixbuf);
02213                 gnome_canvas_item_set (anchorsItem->item,
02214                                     "pixbuf", pixbuf2,
02215                                     NULL);
02216                 gdk_pixbuf_unref(pixbuf2);
02217               }
02218              }
02219            }
02220            break;
02221          default:
02222            break;
02223          }
02224          break;
02225 
02226        case 2:
02227          // Shortcut for the Delete operation
02228          if(selected_anchors_item == anchorsItem)
02229            selected_anchors_item = NULL;
02230 
02231          gtk_object_destroy (GTK_OBJECT(anchorsItem->rootitem));
02232          g_free(anchorsItem);
02233          break;
02234 
02235        case 3:
02236          switch(currentTool) {
02237            /* Perform the reverse operation when it makes sense */
02238          case TOOL_ROTATE_CW:
02239            gc_item_rotate_relative(anchorsItem->rootitem, -10);
02240            reset_anchors_bounded(anchorsItem);
02241            break;
02242          case TOOL_ROTATE_CCW:
02243            gc_item_rotate_relative(anchorsItem->rootitem, 10);
02244            reset_anchors_bounded(anchorsItem);
02245            break;
02246          case TOOL_RAISE:
02247            gnome_canvas_item_lower(anchorsItem->rootitem, 1);
02248            break;
02249          case TOOL_LOWER:
02250            gnome_canvas_item_raise(anchorsItem->rootitem, 1);
02251            break;
02252 
02253          default:
02254            // Shortcut for the Raise operation
02255            gnome_canvas_item_raise_to_top(item);
02256            break;
02257          }
02258          break;
02259 
02260        default:
02261          break;
02262        }
02263       break;
02264     case GDK_BUTTON_RELEASE:
02265       if(dragging)
02266        {
02267          gc_canvas_item_ungrab(item, event->button.time);
02268          dragging = FALSE;
02269          draggingItem = NULL;
02270 
02271          /* Moving back the anchors around their shape */
02272          display_anchors(anchorsItem, TRUE);
02273 
02274        }
02275       break;
02276     case GDK_ENTER_NOTIFY:
02277       switch(currentTool) {
02278       case TOOL_RECT:
02279       case TOOL_FILLED_RECT:
02280       case TOOL_CIRCLE:
02281       case TOOL_FILLED_CIRCLE:
02282       case TOOL_LINE:
02283       case TOOL_FLIP:
02284       case TOOL_DELETE:
02285       case TOOL_FILL:
02286       case TOOL_TEXT:
02287        gc_cursor_set(get_tool_cursor(currentTool));
02288        break;
02289       case TOOL_SELECT:
02290        gc_cursor_set(GDK_FLEUR);
02291        break;
02292       default:
02293        break;
02294       }
02295       break;
02296     case GDK_LEAVE_NOTIFY:
02297       gc_cursor_set(get_tool_cursor(currentTool));
02298       break;
02299 
02300     case GDK_MOTION_NOTIFY:
02301       if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
02302        {
02303          double x1, y1, x2, y2;
02304 
02305          item_x = event->button.x;
02306          item_y = event->button.y;
02307          gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
02308 
02309          new_x = item_x;
02310          new_y = item_y;
02311 
02312          gnome_canvas_item_get_bounds  (item,
02313                                     &x1,
02314                                     &y1,
02315                                     &x2,
02316                                     &y2);
02317 
02318          /* Manage border limits */
02319          if((x1 + new_x - x) < drawing_area_x1 && (new_x - x)<0)
02320            new_x = x;
02321          else if((x2 + new_x -x) > drawing_area_x2 && (new_x - x)>0)
02322            new_x = x;
02323 
02324          if((y1 + new_y - y) < drawing_area_y1 && (new_y - y)<0)
02325            new_y = y;
02326          else if((y2 + new_y - y) > drawing_area_y2 && (new_y - y)>0)
02327            new_y = y;
02328 
02329          snap_to_grid(&new_x, &new_y);
02330          gnome_canvas_item_move(item, new_x - x, new_y - y);
02331 
02332          x = new_x;
02333          y = new_y;
02334        }
02335       break;
02336     default:
02337       break;
02338     }
02339 
02340   return(TRUE);
02341 }
02342 
02343 /*
02344  * Event that occur when a creation of object is requested
02345  *
02346  */
02347 static gint
02348 item_event(GnomeCanvasItem *item, GdkEvent *event, void *shape)
02349 {
02350   static double x, y;
02351   double item_x, item_y;
02352   GnomeCanvasItem *newItem = NULL;
02353 
02354   if(!gcomprisBoard || board_paused)
02355     return FALSE;
02356 
02357   switch (event->type)
02358     {
02359     case GDK_BUTTON_PRESS:
02360       switch(event->button.button)
02361        {
02362        case 1:
02363        case 2:
02364        case 3:
02365          item_x = event->button.x;
02366          item_y = event->button.y;
02367          gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
02368 
02369          x = item_x;
02370          y = item_y;
02371 
02372          switch(currentTool) {
02373          case TOOL_RECT:
02374          case TOOL_FILLED_RECT:
02375          case TOOL_CIRCLE:
02376          case TOOL_FILLED_CIRCLE:
02377          case TOOL_LINE:
02378          case TOOL_TEXT:
02379            // Create a new item
02380            if(event->button.button==1)
02381              {
02382               snap_to_grid(&x, &y);
02383               newItem = create_item(x, y, NULL);
02384 
02385               if(newItem==NULL)
02386                 return FALSE;
02387              }
02388            set_current_tool(selectionToolItem, TOOL_SELECT);
02389            break;
02390          case TOOL_SELECT:
02391            set_selected_item(NULL);
02392            break;
02393          default:
02394            break;
02395          }
02396 
02397        default:
02398          break;
02399        }
02400       break;
02401 
02402     case GDK_ENTER_NOTIFY:
02403       gc_cursor_set(get_tool_cursor(currentTool));
02404       break;
02405 
02406     case GDK_LEAVE_NOTIFY:
02407       gc_cursor_set(GCOMPRIS_DEFAULT_CURSOR);
02408       break;
02409 
02410     case GDK_MOTION_NOTIFY:
02411       break;
02412 
02413     case GDK_BUTTON_RELEASE:
02414       break;
02415 
02416     default:
02417       break;
02418     }
02419 
02420   return TRUE;
02421 }