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_rectangle.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-22  |  15.8 KB  |  507 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 "config.h"
  25. #include "libgimp/stdplugins-intl.h"
  26. #include "imap_main.h"
  27. #include "imap_misc.h"
  28. #include "imap_object_popup.h"
  29. #include "imap_rectangle.h"
  30. #include "imap_table.h"
  31.  
  32. #include "rectangle.xpm"
  33.  
  34. static gboolean rectangle_is_valid(Object_t *obj);
  35. static Object_t *rectangle_clone(Object_t *obj);
  36. static void rectangle_assign(Object_t *obj, Object_t *des);
  37. static void rectangle_normalize(Object_t *obj);
  38. static void rectangle_draw(Object_t *obj, GdkWindow *window, GdkGC* gc);
  39. static void rectangle_draw_sashes(Object_t *obj, GdkWindow *window, GdkGC* gc);
  40. static MoveSashFunc_t rectangle_near_sash(Object_t *obj, gint x, gint y);
  41. static gboolean rectangle_point_is_on(Object_t *obj, gint x, gint y);
  42. static void rectangle_get_dimensions(Object_t *obj, gint *x, gint *y,
  43.                      gint *width, gint *height);
  44. static void rectangle_resize(Object_t *obj, gint percentage_x, 
  45.                  gint percentage_y);
  46. static void rectangle_move(Object_t *obj, gint dx, gint dy);
  47. static gpointer rectangle_create_info_widget(GtkWidget *frame);
  48. static void rectangle_fill_info_tab(Object_t *obj, gpointer data);
  49. static void rectangle_set_initial_focus(Object_t *obj, gpointer data);
  50. static void rectangle_update(Object_t *obj, gpointer data);
  51. static void rectangle_write_csim(Object_t *obj, gpointer param, 
  52.                  OutputFunc_t output);
  53. static void rectangle_write_cern(Object_t *obj, gpointer param, 
  54.                  OutputFunc_t output);
  55. static void rectangle_write_ncsa(Object_t *obj, gpointer param, 
  56.                  OutputFunc_t output);
  57. static char** rectangle_get_icon_data(void);
  58.  
  59. static ObjectClass_t rectangle_class = {
  60.    N_("Rectangle"),
  61.    NULL,            /* info_dialog */
  62.    NULL,            /* icon */
  63.    NULL,            /* mask */
  64.  
  65.    rectangle_is_valid,
  66.    NULL,            /* rectangle_destruct */
  67.    rectangle_clone,
  68.    rectangle_assign,
  69.    rectangle_normalize,
  70.    rectangle_draw,
  71.    rectangle_draw_sashes,
  72.    rectangle_near_sash,
  73.    rectangle_point_is_on,
  74.    rectangle_get_dimensions,
  75.    rectangle_resize,
  76.    rectangle_move,
  77.    rectangle_create_info_widget,
  78.    rectangle_fill_info_tab,    /* rectangle_update_info_widget */
  79.    rectangle_fill_info_tab,
  80.    rectangle_set_initial_focus,
  81.    rectangle_update,
  82.    rectangle_write_csim,
  83.    rectangle_write_cern,
  84.    rectangle_write_ncsa,
  85.    object_do_popup,
  86.    rectangle_get_icon_data
  87. };
  88.  
  89. Object_t*
  90. create_rectangle(gint x, gint y, gint width, gint height)
  91. {
  92.    Rectangle_t *rectangle = g_new(Rectangle_t, 1);
  93.    rectangle->x = x;
  94.    rectangle->y = y;
  95.    rectangle->width = width;
  96.    rectangle->height = height;
  97.    return object_init(&rectangle->obj, &rectangle_class);
  98. }
  99.  
  100. static void
  101. draw_any_rectangle(GdkWindow *window, GdkGC *gc, gint x, gint y, gint w, 
  102.            gint h)
  103. {
  104.    if (w < 0) {
  105.       x += w;
  106.       w = -w;
  107.    }
  108.    if (h < 0) {
  109.       y += h;
  110.       h = -h;
  111.    }
  112.    draw_rectangle(window, gc, FALSE, x, y, w, h);
  113. }
  114.  
  115. static gboolean
  116. rectangle_is_valid(Object_t *obj)
  117. {
  118.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  119.    return rectangle->width && rectangle->height;
  120. }
  121.  
  122. static Object_t*
  123. rectangle_clone(Object_t *obj)
  124. {
  125.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  126.    Rectangle_t *clone = g_new(Rectangle_t, 1);
  127.  
  128.    clone->x = rectangle->x;
  129.    clone->y = rectangle->y;
  130.    clone->width = rectangle->width;
  131.    clone->height = rectangle->height;
  132.    return &clone->obj;
  133. }
  134.  
  135. static void
  136. rectangle_assign(Object_t *obj, Object_t *des)
  137. {
  138.    Rectangle_t *src_rectangle = ObjectToRectangle(obj);
  139.    Rectangle_t *des_rectangle = ObjectToRectangle(des);
  140.    des_rectangle->x = src_rectangle->x;
  141.    des_rectangle->y = src_rectangle->y;
  142.    des_rectangle->width = src_rectangle->width;
  143.    des_rectangle->height = src_rectangle->height;
  144. }
  145.  
  146. static void
  147. rectangle_normalize(Object_t *obj)
  148. {
  149.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  150.    if (rectangle->width < 0) {
  151.       rectangle->x += rectangle->width;
  152.       rectangle->width = -rectangle->width;
  153.    }
  154.    if (rectangle->height < 0) {
  155.       rectangle->y += rectangle->height;
  156.       rectangle->height = -rectangle->height;
  157.    }
  158. }
  159.  
  160. static void
  161. rectangle_draw(Object_t *obj, GdkWindow *window, GdkGC *gc)
  162. {
  163.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  164.    draw_any_rectangle(window, gc, rectangle->x, rectangle->y,
  165.               rectangle->width, rectangle->height);
  166. }
  167.  
  168. static void
  169. rectangle_draw_sashes(Object_t *obj, GdkWindow *window, GdkGC *gc)
  170. {
  171.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  172.    draw_sash(window, gc, rectangle->x, rectangle->y);
  173.    draw_sash(window, gc, rectangle->x + rectangle->width / 2, rectangle->y);
  174.    draw_sash(window, gc, rectangle->x + rectangle->width, rectangle->y);
  175.    draw_sash(window, gc, rectangle->x, rectangle->y + rectangle->height / 2);
  176.    draw_sash(window, gc, rectangle->x + rectangle->width, 
  177.          rectangle->y + rectangle->height / 2);
  178.    draw_sash(window, gc, rectangle->x, rectangle->y + rectangle->height);
  179.    draw_sash(window, gc, rectangle->x + rectangle->width / 2, 
  180.          rectangle->y + rectangle->height);
  181.    draw_sash(window, gc, rectangle->x + rectangle->width, 
  182.          rectangle->y + rectangle->height);
  183. }
  184.  
  185. static void
  186. MoveUpperSash(Object_t *obj, gint dx, gint dy)
  187. {
  188.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  189.    rectangle->y += dy;
  190.    rectangle->height -= dy;
  191. }
  192.  
  193. static void
  194. MoveLeftSash(Object_t *obj, gint dx, gint dy)
  195. {
  196.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  197.    rectangle->x += dx;
  198.    rectangle->width -= dx;
  199. }
  200.  
  201. static void
  202. MoveRightSash(Object_t *obj, gint dx, gint dy)
  203. {
  204.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  205.    rectangle->width += dx;
  206. }
  207.  
  208. static void
  209. MoveLowerSash(Object_t *obj, gint dx, gint dy)
  210. {
  211.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  212.    rectangle->height += dy;
  213. }
  214.  
  215. static void
  216. MoveUpperLeftSash(Object_t *obj, gint dx, gint dy)
  217. {
  218.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  219.    rectangle->x += dx;
  220.    rectangle->y += dy;
  221.    rectangle->width -= dx;
  222.    rectangle->height -= dy;
  223. }
  224.  
  225. static void
  226. MoveUpperRightSash(Object_t *obj, gint dx, gint dy)
  227. {
  228.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  229.    rectangle->y += dy;
  230.    rectangle->width += dx;
  231.    rectangle->height -= dy;
  232. }
  233.  
  234. static void
  235. MoveLowerLeftSash(Object_t *obj, gint dx, gint dy)
  236. {
  237.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  238.    rectangle->x += dx;
  239.    rectangle->width -= dx;
  240.    rectangle->height += dy;
  241. }
  242.  
  243. static void
  244. MoveLowerRightSash(Object_t *obj, gint dx, gint dy)
  245. {
  246.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  247.    rectangle->width += dx;
  248.    rectangle->height += dy;
  249. }
  250.  
  251. static MoveSashFunc_t
  252. rectangle_near_sash(Object_t *obj, gint x, gint y)
  253. {
  254.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  255.    if (near_sash(rectangle->x, rectangle->y, x, y))
  256.       return MoveUpperLeftSash;
  257.    else if (near_sash(rectangle->x + rectangle->width / 2, rectangle->y, x, y))
  258.       return MoveUpperSash;
  259.    else if (near_sash(rectangle->x + rectangle->width, rectangle->y, x, y))
  260.       return MoveUpperRightSash;
  261.    else if (near_sash(rectangle->x, rectangle->y + rectangle->height / 2, 
  262.               x, y))
  263.       return MoveLeftSash;
  264.    else if (near_sash(rectangle->x + rectangle->width, 
  265.               rectangle->y + rectangle->height / 2, x, y))
  266.       return MoveRightSash;
  267.    else if (near_sash(rectangle->x, rectangle->y + rectangle->height, x, y))
  268.       return MoveLowerLeftSash;
  269.    else if (near_sash(rectangle->x + rectangle->width / 2, 
  270.               rectangle->y + rectangle->height, x, y))
  271.       return MoveLowerSash;
  272.    else if (near_sash(rectangle->x + rectangle->width, 
  273.               rectangle->y + rectangle->height, x, y))
  274.       return MoveLowerRightSash;
  275.    return NULL;
  276. }
  277.  
  278. static gboolean
  279. rectangle_point_is_on(Object_t *obj, gint x, gint y)
  280. {
  281.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  282.    return x >= rectangle->x && x <= rectangle->x + rectangle->width &&
  283.       y >= rectangle->y && y <= rectangle->y + rectangle->height;
  284. }
  285.  
  286. static void 
  287. rectangle_get_dimensions(Object_t *obj, gint *x, gint *y,
  288.              gint *width, gint *height)
  289. {
  290.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  291.    *x = rectangle->x;
  292.    *y = rectangle->y;
  293.    *width = rectangle->width;
  294.    *height = rectangle->height;
  295. }
  296.  
  297. static void 
  298. rectangle_resize(Object_t *obj, gint percentage_x, gint percentage_y)
  299. {
  300.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  301.    rectangle->x = rectangle->x * percentage_x / 100;
  302.    rectangle->y = rectangle->y * percentage_y / 100;
  303.    rectangle->width = rectangle->width * percentage_x / 100;
  304.    rectangle->height = rectangle->height * percentage_y / 100;
  305. }
  306.  
  307. static void
  308. rectangle_move(Object_t *obj, gint dx, gint dy)
  309. {
  310.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  311.    rectangle->x += dx;
  312.    rectangle->y += dy;
  313. }
  314.  
  315. typedef struct {
  316.    Object_t  *obj;
  317.    GtkWidget *x;
  318.    GtkWidget *y;
  319.    GtkWidget *width;
  320.    GtkWidget *height;
  321. } RectangleProperties_t;
  322.  
  323. static void
  324. x_changed_cb(GtkWidget *widget, gpointer data)
  325. {
  326.    Object_t *obj = ((RectangleProperties_t*) data)->obj;
  327.    gint x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  328.    ObjectToRectangle(obj)->x = x;
  329.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  330. }
  331.  
  332. static void
  333. y_changed_cb(GtkWidget *widget, gpointer data)
  334. {
  335.    Object_t *obj = ((RectangleProperties_t*) data)->obj;
  336.    gint y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  337.    ObjectToRectangle(obj)->y = y;
  338.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  339. }
  340.  
  341. static void
  342. width_changed_cb(GtkWidget *widget, gpointer data)
  343. {
  344.    Object_t *obj = ((RectangleProperties_t*) data)->obj;
  345.    gint width = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  346.    ObjectToRectangle(obj)->width = width;
  347.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  348. }
  349.  
  350. static void
  351. height_changed_cb(GtkWidget *widget, gpointer data)
  352. {
  353.    Object_t *obj = ((RectangleProperties_t*) data)->obj;
  354.    gint height = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  355.    ObjectToRectangle(obj)->height = height;
  356.    edit_area_info_dialog_emit_geometry_signal(obj->class->info_dialog);
  357. }
  358.  
  359. static gpointer
  360. rectangle_create_info_widget(GtkWidget *frame)
  361. {
  362.    RectangleProperties_t *props = g_new(RectangleProperties_t, 1);
  363.    GtkWidget *table;
  364.    gint max_width = get_image_width();
  365.    gint max_height = get_image_height();
  366.  
  367.    table = gtk_table_new(4, 3, FALSE);
  368.    gtk_container_add(GTK_CONTAINER(frame), table);
  369.    gtk_container_set_border_width(GTK_CONTAINER(table), 10);
  370.  
  371.    gtk_table_set_row_spacings(GTK_TABLE(table), 10);
  372.    gtk_table_set_col_spacings(GTK_TABLE(table), 10);
  373.    gtk_widget_show(table);
  374.    
  375.    create_label_in_table(table, 0, 0, _("Upper left x:"));
  376.    props->x = create_spin_button_in_table(table, 0, 1, 1, 0, max_width - 1);
  377.    gtk_signal_connect(GTK_OBJECT(props->x), "changed", 
  378.               (GtkSignalFunc) x_changed_cb, (gpointer) props);
  379.    create_label_in_table(table, 0, 2, _("pixels"));
  380.  
  381.    create_label_in_table(table, 1, 0, _("Upper left y:"));
  382.    props->y = create_spin_button_in_table(table, 1, 1, 1, 0, max_height - 1);
  383.    gtk_signal_connect(GTK_OBJECT(props->y), "changed", 
  384.               (GtkSignalFunc) y_changed_cb, (gpointer) props);
  385.    create_label_in_table(table, 1, 2, _("pixels"));
  386.  
  387.    create_label_in_table(table, 2, 0, _("Width:"));
  388.    props->width = create_spin_button_in_table(table, 2, 1, 1, 1, max_width);
  389.    gtk_signal_connect(GTK_OBJECT(props->width), "changed", 
  390.               (GtkSignalFunc) width_changed_cb, (gpointer) props);
  391.    create_label_in_table(table, 2, 2, _("pixels"));
  392.  
  393.    create_label_in_table(table, 3, 0, _("Height:"));
  394.    props->height = create_spin_button_in_table(table, 3, 1, 1, 1, max_height);
  395.    gtk_signal_connect(GTK_OBJECT(props->height), "changed", 
  396.               (GtkSignalFunc) height_changed_cb, (gpointer) props);
  397.    create_label_in_table(table, 3, 2, _("pixels"));
  398.  
  399.    return props;
  400. }
  401.  
  402. static void 
  403. rectangle_fill_info_tab(Object_t *obj, gpointer data)
  404. {
  405.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  406.    RectangleProperties_t *props = (RectangleProperties_t*) data;
  407.  
  408.    props->obj = obj;
  409.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->x), rectangle->x);
  410.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->y), rectangle->y);
  411.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->width), rectangle->width);
  412.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(props->height), 
  413.                  rectangle->height);
  414. }
  415.  
  416. static void 
  417. rectangle_set_initial_focus(Object_t *obj, gpointer data)
  418. {
  419.    RectangleProperties_t *props = (RectangleProperties_t*) data;
  420.    gtk_widget_grab_focus(props->x);
  421. }
  422.  
  423. static void 
  424. rectangle_update(Object_t* obj, gpointer data)
  425. {
  426.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  427.    RectangleProperties_t *props = (RectangleProperties_t*) data;
  428.  
  429.    rectangle->x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->x));
  430.    rectangle->y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(props->y));
  431.    rectangle->width = gtk_spin_button_get_value_as_int(
  432.       GTK_SPIN_BUTTON(props->width));
  433.    rectangle->height = gtk_spin_button_get_value_as_int(
  434.       GTK_SPIN_BUTTON(props->height));
  435. }
  436.  
  437. static void
  438. rectangle_write_csim(Object_t *obj, gpointer param, OutputFunc_t output)
  439. {
  440.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  441.    output(param, "\"RECT\" COORDS=\"%d,%d,%d,%d\"", rectangle->x, rectangle->y,
  442.       rectangle->x + rectangle->width, rectangle->y + rectangle->height);
  443. }
  444.  
  445. static void
  446. rectangle_write_cern(Object_t *obj, gpointer param, OutputFunc_t output)
  447. {
  448.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  449.    output(param, "rect (%d,%d) (%d,%d)", rectangle->x, rectangle->y,
  450.       rectangle->x + rectangle->width, rectangle->y + rectangle->height);
  451. }
  452.  
  453. static void
  454. rectangle_write_ncsa(Object_t *obj, gpointer param, OutputFunc_t output)
  455. {
  456.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  457.    output(param, "rect %s %d,%d %d,%d", obj->url,
  458.       rectangle->x, rectangle->y,
  459.       rectangle->x + rectangle->width, rectangle->y + rectangle->height);
  460. }
  461.  
  462. static char**
  463. rectangle_get_icon_data(void)
  464. {
  465.    return rectangle_xpm;
  466. }
  467.  
  468. static Object_t*
  469. rectangle_factory_create_object(gint x, gint y)
  470. {
  471.    return create_rectangle(x, y, 0, 0);
  472. }
  473.  
  474. static void
  475. rectangle_factory_set_xy(Object_t *obj, guint state, gint x, gint y)
  476. {
  477.    Rectangle_t *rectangle = ObjectToRectangle(obj);
  478.  
  479.    rectangle->width = x - rectangle->x;
  480.    rectangle->height = y - rectangle->y;
  481.  
  482.    if (state & GDK_SHIFT_MASK){
  483.       gint width = abs(rectangle->width);
  484.       gint height = abs(rectangle->height);
  485.       if (width < height)
  486.      rectangle->height = (rectangle->height < 0) ? -width : width;
  487.       else
  488.      rectangle->width = (rectangle->width < 0) ? -height : height;
  489.    }
  490.  
  491.    main_set_dimension(rectangle->width, rectangle->height);
  492. }
  493.  
  494. static ObjectFactory_t rectangle_factory = {
  495.    NULL,            /* Object pointer */
  496.    NULL,            /* Finish func */
  497.    NULL,            /* Cancel func */
  498.    rectangle_factory_create_object,
  499.    rectangle_factory_set_xy
  500. };
  501.  
  502. ObjectFactory_t*
  503. get_rectangle_factory(guint state)
  504. {
  505.    return &rectangle_factory;
  506. }
  507.