home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / imagemap / imap_circle.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-23  |  11.7 KB  |  404 lines

  1. /*
  2.  * This is a plug-in for the GIMP.
  3.  *
  4.  * Generates clickable image maps.
  5.  *
  6.  * Copyright (C) 1998-1999 Maurits Rijk  lpeek.mrijk@consunet.nl
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  *
  22.  */
  23.  
  24. #include <math.h>
  25.  
  26. #include "config.h"
  27. #include "imap_circle.h"
  28. #include "libgimp/stdplugins-intl.h"
  29. #include "imap_main.h"
  30. #include "imap_misc.h"
  31. #include "imap_object_popup.h"
  32. #include "imap_table.h"
  33.  
  34. #include "circle.xpm"
  35.  
  36. static gboolean circle_is_valid(Object_t *obj);
  37. static Object_t *circle_clone(Object_t *obj);
  38. static void circle_assign(Object_t *obj, Object_t *des);
  39. static void circle_draw(Object_t* obj, GdkWindow *window, GdkGC* gc);
  40. static void circle_draw_sashes(Object_t* obj, GdkWindow *window, GdkGC* gc);
  41. static MoveSashFunc_t circle_near_sash(Object_t *obj, gint x, gint y);
  42. static gboolean circle_point_is_on(Object_t *obj, gint x, gint y);
  43. static void circle_get_dimensions(Object_t *obj, gint *x, gint *y,
  44.                   gint *width, gint *height);
  45. static void circle_resize(Object_t *obj, gint percentage_x, gint percentage_y);
  46. static void circle_move(Object_t *obj, gint dx, gint dy);
  47. static gpointer circle_create_info_widget(GtkWidget *frame);
  48. static void circle_fill_info_tab(Object_t *obj, gpointer data);
  49. static void circle_set_initial_focus(Object_t *obj, gpointer data);
  50. static void circle_update(Object_t* obj, gpointer data);
  51. static void circle_write_csim(Object_t* obj, gpointer param, 
  52.                   OutputFunc_t output);
  53. static void circle_write_cern(Object_t* obj, gpointer param, 
  54.                   OutputFunc_t output);
  55. static void circle_write_ncsa(Object_t* obj, gpointer param, 
  56.                   OutputFunc_t output);
  57. static char** circle_get_icon_data(void);
  58.  
  59. static ObjectClass_t circle_class = {
  60.    N_("Circle"),
  61.    NULL,            /* info_dialog */
  62.    NULL,            /* icon */
  63.    NULL,            /* mask */
  64.  
  65.    circle_is_valid,
  66.    NULL,            /* circle_destruct */
  67.    circle_clone,
  68.    circle_assign,
  69.    NULL,            /* circle_normalize */
  70.    circle_draw,
  71.    circle_draw_sashes,
  72.    circle_near_sash,
  73.    circle_point_is_on,
  74.    circle_get_dimensions,
  75.    circle_resize,
  76.    circle_move,
  77.    circle_create_info_widget,
  78.    circle_fill_info_tab,    /* circle_update_info_widget */
  79.    circle_fill_info_tab,
  80.    circle_set_initial_focus,
  81.    circle_update,
  82.    circle_write_csim,
  83.    circle_write_cern,
  84.    circle_write_ncsa,
  85.    object_do_popup,
  86.    circle_get_icon_data
  87. };
  88.  
  89. Object_t*
  90. create_circle(gint x, gint y, gint r)
  91. {
  92.    Circle_t *circle = g_new(Circle_t, 1);
  93.    circle->x = x;
  94.    circle->y = y;
  95.    circle->r = r;
  96.    return object_init(&circle->obj, &circle_class);
  97. }
  98.  
  99. static gboolean
  100. circle_is_valid(Object_t *obj)
  101. {
  102.    return ObjectToCircle(obj)->r > 0;
  103. }
  104.  
  105. static Object_t*
  106. circle_clone(Object_t *obj)
  107. {
  108.    Circle_t *circle = ObjectToCircle(obj);
  109.    Circle_t *clone = g_new(Circle_t, 1);
  110.  
  111.    clone->x = circle->x;
  112.    clone->y = circle->y;
  113.    clone->r = circle->r;
  114.    return &clone->obj;
  115. }
  116.  
  117. static void
  118. circle_assign(Object_t *obj, Object_t *des)
  119. {
  120.    Circle_t *src_circle = ObjectToCircle(obj);
  121.    Circle_t *des_circle = ObjectToCircle(des);
  122.    des_circle->x = src_circle->x;
  123.    des_circle->y = src_circle->y;
  124.    des_circle->r = src_circle->r;
  125. }
  126.  
  127. static void
  128. circle_draw(Object_t *obj, GdkWindow *window, GdkGC *gc)
  129. {
  130.    Circle_t *circle = ObjectToCircle(obj);
  131.    draw_circle(window, gc, FALSE, circle->x, circle->y, circle->r);
  132. }
  133.  
  134. static void
  135. circle_draw_sashes(Object_t *obj, GdkWindow *window, GdkGC *gc)
  136. {
  137.    Circle_t *circle = ObjectToCircle(obj);
  138.    draw_sash(window, gc, circle->x - circle->r, circle->y - circle->r);
  139.    draw_sash(window, gc, circle->x + circle->r, circle->y - circle->r);
  140.    draw_sash(window, gc, circle->x - circle->r, circle->y + circle->r);
  141.    draw_sash(window, gc, circle->x + circle->r, circle->y + circle->r);
  142. }
  143.  
  144. static gint sash_x;
  145. static gint sash_y;
  146.  
  147. static void
  148. move_sash(Object_t *obj, gint dx, gint dy)
  149. {
  150.    Circle_t *circle = ObjectToCircle(obj);
  151.    gint rx, ry;
  152.    sash_x += dx;
  153.    sash_y += dy;
  154.  
  155.    rx = abs(circle->x - sash_x);
  156.    ry = abs(circle->y - sash_y);
  157.    circle->r = (rx > ry) ? rx : ry;
  158. }
  159.  
  160. static void 
  161. circle_resize(Object_t *obj, gint percentage_x, gint percentage_y)
  162. {
  163.    Circle_t *circle = ObjectToCircle(obj);
  164.    circle->x = circle->x * percentage_x / 100;
  165.    circle->y = circle->y * percentage_y / 100;
  166.    circle->r = circle->r * ((percentage_x < percentage_y) 
  167.                 ? percentage_x : percentage_y) / 100;
  168. }
  169.  
  170. static MoveSashFunc_t
  171. circle_near_sash(Object_t *obj, gint x, gint y)
  172. {
  173.    Circle_t *circle = ObjectToCircle(obj);
  174.    sash_x = x;
  175.    sash_y = y;
  176.    if (near_sash(circle->x - circle->r, circle->y - circle->r, x, y) ||
  177.        near_sash(circle->x + circle->r, circle->y - circle->r, x, y) ||
  178.        near_sash(circle->x - circle->r, circle->y + circle->r, x, y) ||
  179.        near_sash(circle->x + circle->r, circle->y + circle->r, x, y))
  180.       return move_sash;
  181.    return NULL;
  182. }
  183.  
  184. static gboolean
  185. circle_point_is_on(Object_t *obj, gint x, gint y)
  186. {
  187.    Circle_t *circle = ObjectToCircle(obj);
  188.    x -= circle->x;
  189.    y -= circle->y;
  190.    return x * x + y * y <= circle->r * circle->r;
  191. }
  192.  
  193. static void 
  194. circle_get_dimensions(Object_t *obj, gint *x, gint *y,
  195.               gint *width, gint *height)
  196. {
  197.    Circle_t *circle = ObjectToCircle(obj);
  198.    *x = circle->x - circle->r;
  199.    *y = circle->y - circle->r;
  200.    *width = *height = 2 * circle->r;
  201. }
  202.  
  203. static void
  204. circle_move(Object_t *obj, gint dx, gint dy)
  205. {
  206.    Circle_t *circle = ObjectToCircle(obj);
  207.    circle->x += dx;
  208.    circle->y += dy;
  209. }
  210.  
  211. typedef struct {
  212.    Object_t  *obj;
  213.    GtkWidget *x;
  214.    GtkWidget *y;
  215.    GtkWidget *r;
  216. } CircleProperties_t;
  217.  
  218. static void
  219. x_changed_cb(GtkWidget *widget, gpointer data)
  220. {
  221.    Object_t *obj = ((CircleProperties_t*) data)->obj;
  222.    gint x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  223.    ObjectToCircle(obj)->x = x;
  224.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  225. }
  226.  
  227. static void
  228. y_changed_cb(GtkWidget *widget, gpointer data)
  229. {
  230.    Object_t *obj = ((CircleProperties_t*) data)->obj;
  231.    gint y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  232.    ObjectToCircle(obj)->y = y;
  233.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  234. }
  235.  
  236. static void
  237. r_changed_cb(GtkWidget *widget, gpointer data)
  238. {
  239.    Object_t *obj = ((CircleProperties_t*) data)->obj;
  240.    gint r = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  241.    ObjectToCircle(obj)->r = r;
  242.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  243. }
  244.  
  245. static gpointer
  246. circle_create_info_widget(GtkWidget *frame)
  247. {
  248.    CircleProperties_t *props = g_new(CircleProperties_t, 1);
  249.    GtkWidget *table;
  250.    gint max_width = get_image_width();
  251.    gint max_height = get_image_height();
  252.  
  253.    table = gtk_table_new(3, 3, FALSE);
  254.    gtk_container_add(GTK_CONTAINER(frame), table);
  255.    gtk_container_set_border_width(GTK_CONTAINER(table), 10);
  256.  
  257.    gtk_table_set_row_spacings(GTK_TABLE(table), 10);
  258.    gtk_table_set_col_spacings(GTK_TABLE(table), 10);
  259.    gtk_widget_show(table);
  260.    
  261.    create_label_in_table(table, 0, 0, _("Center x:"));
  262.    props->x = create_spin_button_in_table(table, 0, 1, 1, 0, max_width - 1);
  263.    gtk_signal_connect(GTK_OBJECT(props->x), "changed", 
  264.               (GtkSignalFunc) x_changed_cb, (gpointer) props);
  265.    create_label_in_table(table, 0, 2, _("pixels"));
  266.  
  267.    create_label_in_table(table, 1, 0, _("Center y:"));
  268.    props->y = create_spin_button_in_table(table, 1, 1, 1, 0, max_height - 1);
  269.    gtk_signal_connect(GTK_OBJECT(props->y), "changed", 
  270.               (GtkSignalFunc) y_changed_cb, (gpointer) props);
  271.    create_label_in_table(table, 1, 2, _("pixels"));
  272.  
  273.    create_label_in_table(table, 2, 0, _("Radius:"));
  274.    props->r = create_spin_button_in_table(table, 2, 1, 1, 1, G_MAXINT);
  275.    gtk_signal_connect(GTK_OBJECT(props->r), "changed", 
  276.               (GtkSignalFunc) r_changed_cb, (gpointer) props);
  277.    create_label_in_table(table, 2, 2, _("pixels"));
  278.  
  279.    return props;
  280. }
  281.  
  282. static void 
  283. circle_fill_info_tab(Object_t *obj, gpointer data)
  284. {
  285.    Circle_t *circle = ObjectToCircle(obj);
  286.    CircleProperties_t *props = (CircleProperties_t*) data;
  287.  
  288.    props->obj = obj;
  289.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->x), circle->x);
  290.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->y), circle->y);
  291.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->r), circle->r);
  292. }
  293.  
  294. static void 
  295. circle_set_initial_focus(Object_t *obj, gpointer data)
  296. {
  297.    CircleProperties_t *props = (CircleProperties_t*) data;
  298.    gtk_widget_grab_focus(props->x);
  299. }
  300.  
  301. static void 
  302. circle_update(Object_t* obj, gpointer data)
  303. {
  304.    Circle_t *circle = ObjectToCircle(obj);
  305.    CircleProperties_t *props = (CircleProperties_t*) data;
  306.  
  307.    circle->x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->x));
  308.    circle->y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->y));
  309.    circle->r = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->r));
  310. }
  311.  
  312. static void
  313. circle_write_csim(Object_t *obj, gpointer param, OutputFunc_t output)
  314. {
  315.    Circle_t *circle = ObjectToCircle(obj);
  316.    output(param, "\"CIRCLE\" COORDS=\"%d,%d,%d\"", circle->x, circle->y,
  317.       circle->r);
  318. }
  319.  
  320. static void
  321. circle_write_cern(Object_t *obj, gpointer param, OutputFunc_t output)
  322. {
  323.    Circle_t *circle = ObjectToCircle(obj);
  324.    output(param, "circ (%d,%d) %d", circle->x, circle->y, circle->r);
  325. }
  326.  
  327. static void
  328. circle_write_ncsa(Object_t *obj, gpointer param, OutputFunc_t output)
  329. {
  330.    Circle_t *circle = ObjectToCircle(obj);
  331.    output(param, "circle %s %d,%d %d,%d", obj->url,
  332.       circle->x, circle->y, circle->x, circle->y + circle->r);
  333. }
  334.  
  335. static char** 
  336. circle_get_icon_data(void)
  337. {
  338.    return circle_xpm;
  339. }
  340.  
  341. static gint _start_x, _start_y;
  342.  
  343. static Object_t*
  344. circle_factory_create_object1(gint x, gint y)
  345. {
  346.    _start_x = x;
  347.    _start_y = y;
  348.    return create_circle(x, y, 0);
  349. }
  350.  
  351. static void
  352. circle_factory_set_xy1(Object_t *obj, guint state, gint x, gint y)
  353. {
  354.    Circle_t *circle = ObjectToCircle(obj);
  355.  
  356.    circle->x = (_start_x + x) / 2;
  357.    circle->y = (_start_y + y) / 2;
  358.    x -= _start_x;
  359.    y -= _start_y;
  360.    circle->r = (gint) sqrt(x * x + y * y) / 2;
  361.  
  362.    main_set_dimension(circle->r, circle->r);
  363. }
  364.  
  365. static ObjectFactory_t circle_factory1 = {
  366.    NULL,            /* Object pointer */
  367.    NULL,            /* Finish func */
  368.    NULL,            /* Cancel func */
  369.    circle_factory_create_object1,
  370.    circle_factory_set_xy1
  371. };
  372.  
  373. static Object_t*
  374. circle_factory_create_object2(gint x, gint y)
  375. {
  376.    return create_circle(x, y, 0);
  377. }
  378.  
  379. static void
  380. circle_factory_set_xy2(Object_t *obj, guint state, gint x, gint y)
  381. {
  382.    Circle_t *circle = ObjectToCircle(obj);
  383.  
  384.    x -= circle->x;
  385.    y -= circle->y;
  386.    circle->r = (gint) sqrt(x * x + y * y);
  387.  
  388.    main_set_dimension(circle->r, circle->r);
  389. }
  390.  
  391. static ObjectFactory_t circle_factory2 = {
  392.    NULL,            /* Object pointer */
  393.    NULL,            /* Finish func */
  394.    NULL,            /* Cancel func */
  395.    circle_factory_create_object2,
  396.    circle_factory_set_xy2
  397. };
  398.  
  399. ObjectFactory_t*
  400. get_circle_factory(guint state)
  401. {
  402.    return (state & GDK_SHIFT_MASK) ? &circle_factory1 : &circle_factory2;
  403. }
  404.