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_grid.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-23  |  11.2 KB  |  359 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 "imap_grid.h"
  26. #include "libgimp/stdplugins-intl.h"
  27. #include "imap_main.h"
  28. #include "imap_menu.h"
  29. #include "imap_popup.h"
  30. #include "imap_preview.h"
  31. #include "imap_table.h"
  32. #include "imap_toolbar.h"
  33.  
  34. typedef enum {GRID_HIDDEN, GRID_LINES, GRID_CROSSES} GridType_t;
  35.  
  36. static GdkGC *grid_gc;
  37. static gboolean grid_snap = FALSE;
  38. static gint grid_width = 15;
  39. static gint grid_height = 15;
  40. static gint grid_left = 0;
  41. static gint grid_top = 0;
  42. static GridType_t grid_type = GRID_LINES;
  43.  
  44. static void
  45. grid_settings_ok_cb(gpointer data)
  46. {
  47.    GridDialog_t *param = (GridDialog_t*) data;
  48.    gint new_snap;
  49.  
  50.    new_snap = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->snap));
  51.    grid_width = gtk_spin_button_get_value_as_int(
  52.       GTK_SPIN_BUTTON(param->width));
  53.    grid_height = gtk_spin_button_get_value_as_int(
  54.       GTK_SPIN_BUTTON(param->height));
  55.    grid_left = gtk_spin_button_get_value_as_int(
  56.       GTK_SPIN_BUTTON(param->left));
  57.    grid_top = gtk_spin_button_get_value_as_int(
  58.       GTK_SPIN_BUTTON(param->top));
  59.  
  60.    if (grid_snap != new_snap) {
  61.       grid_snap = new_snap;
  62.       main_toolbar_set_grid(grid_snap);
  63.       popup_check_grid(grid_snap);
  64.       menu_check_grid(grid_snap);
  65.    }
  66.    redraw_preview();
  67. }
  68.  
  69. static void
  70. snap_toggled_cb(GtkWidget *widget, gpointer data)
  71. {
  72.    GridDialog_t *param = (GridDialog_t*) data;
  73.    gint sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  74.  
  75.    gtk_widget_set_sensitive(param->type_frame, sensitive);
  76.    gtk_widget_set_sensitive(param->granularity_frame, sensitive);
  77.    gtk_widget_set_sensitive(param->offset_frame, sensitive);
  78.    gtk_widget_set_sensitive(param->preview, sensitive);
  79. }
  80.  
  81. static void
  82. type_toggled_cb(GtkWidget *widget, gpointer data)
  83. {
  84.    if (GTK_WIDGET_STATE(widget) & GTK_STATE_SELECTED) {
  85.       grid_type = (gint) data;
  86.       redraw_preview();
  87.    }
  88. }
  89.  
  90. static void
  91. toggle_preview_cb(GtkWidget *widget, GridDialog_t *param)
  92. {
  93.    param->enable_preview = 
  94.       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  95.    redraw_preview();
  96. }
  97.  
  98. static void
  99. grid_assign_value(GtkWidget *widget, gpointer data, gint *value)
  100. {
  101.    GridDialog_t *dialog = (GridDialog_t*) data;
  102.    if (dialog->enable_preview) {
  103.       *value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  104.       redraw_preview();        /* Fix me! */
  105.    }
  106. }
  107.  
  108. static void
  109. width_changed_cb(GtkWidget *widget, gpointer data)
  110. {
  111.    grid_assign_value(widget, data, &grid_width);
  112. }
  113.  
  114. static void
  115. height_changed_cb(GtkWidget *widget, gpointer data)
  116. {
  117.    grid_assign_value(widget, data, &grid_height);
  118. }
  119.  
  120. static void
  121. left_changed_cb(GtkWidget *widget, gpointer data)
  122. {
  123.    grid_assign_value(widget, data, &grid_left);
  124. }
  125.  
  126. static void
  127. top_changed_cb(GtkWidget *widget, gpointer data)
  128. {
  129.    grid_assign_value(widget, data, &grid_top);
  130. }
  131.  
  132. static GridDialog_t*
  133. create_grid_settings_dialog()
  134. {
  135.    GridDialog_t *data = g_new(GridDialog_t, 1);
  136.    DefaultDialog_t *dialog;
  137.    GtkWidget *main_table, *table;
  138.    GtkWidget *frame;
  139.    GtkWidget *hbox;
  140.    GtkWidget *button;
  141.    GSList* group;
  142.    
  143.    data->dialog = dialog = make_default_dialog(_("Grid Settings"));
  144.    default_dialog_set_ok_cb(dialog, grid_settings_ok_cb, (gpointer) data);
  145.    
  146.    main_table = gtk_table_new(4, 2, FALSE);
  147.    gtk_container_set_border_width(GTK_CONTAINER(main_table), 10);
  148.    gtk_table_set_row_spacings(GTK_TABLE(main_table), 10);
  149.    gtk_table_set_col_spacings(GTK_TABLE(main_table), 10);
  150.    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog->dialog)->vbox), 
  151.               main_table, TRUE, TRUE, 10);
  152.    gtk_widget_show(main_table);
  153.    
  154.    data->snap = gtk_check_button_new_with_label(_("Snap-To Grid Enabled"));
  155.    gtk_signal_connect(GTK_OBJECT(data->snap), "toggled", 
  156.               (GtkSignalFunc) snap_toggled_cb, data);
  157.    gtk_table_attach_defaults(GTK_TABLE(main_table), data->snap, 0, 1, 0, 1);
  158.    gtk_widget_show(data->snap);
  159.    
  160.    data->type_frame = frame = gtk_frame_new(_("Grid Visibility and Type"));
  161.    gtk_widget_show(frame);
  162.    gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 0, 2, 1, 2);
  163.    hbox = gtk_hbox_new(FALSE, 1);
  164.    gtk_container_add(GTK_CONTAINER(frame), hbox);
  165.    gtk_widget_show(hbox);
  166.  
  167.    data->hidden = button = gtk_radio_button_new_with_label(NULL, _("Hidden"));
  168.    gtk_signal_connect(GTK_OBJECT(button), "toggled", 
  169.               (GtkSignalFunc) type_toggled_cb, (gpointer) GRID_HIDDEN);
  170.    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10);
  171.    gtk_widget_show(button);
  172.  
  173.    group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
  174.    data->lines = button = gtk_radio_button_new_with_label(group, _("Lines"));
  175.    gtk_signal_connect(GTK_OBJECT(button), "toggled", 
  176.               (GtkSignalFunc) type_toggled_cb, (gpointer) GRID_LINES);
  177.    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
  178.    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10);
  179.    gtk_widget_show(button);
  180.  
  181.    group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
  182.    data->crosses = button = gtk_radio_button_new_with_label(group, 
  183.                                 _("Crosses"));
  184.    gtk_signal_connect(GTK_OBJECT(button), "toggled", 
  185.               (GtkSignalFunc) type_toggled_cb, 
  186.               (gpointer) GRID_CROSSES);
  187.    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10);
  188.    gtk_widget_show(button);
  189.    
  190.    data->granularity_frame = frame = gtk_frame_new(_("Grid Granularity"));
  191.    gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 0, 1, 2, 3);
  192.    table = gtk_table_new(2, 3, FALSE);
  193.    gtk_container_set_border_width(GTK_CONTAINER(table), 10);
  194.    gtk_table_set_row_spacings(GTK_TABLE(table), 10);
  195.    gtk_table_set_col_spacings(GTK_TABLE(table), 10);
  196.    gtk_container_add(GTK_CONTAINER(frame), table);
  197.  
  198.    create_label_in_table(table, 0, 0, _("Width"));
  199.    data->width = create_spin_button_in_table(table, 0, 1, 15, 1, 100);
  200.    gtk_signal_connect(GTK_OBJECT(data->width), "changed", 
  201.               (GtkSignalFunc) width_changed_cb, (gpointer) data);
  202.    create_label_in_table(table, 0, 2, _("pixels"));
  203.  
  204.    create_label_in_table(table, 1, 0, _("Height"));
  205.    data->height = create_spin_button_in_table(table, 1, 1, 15, 1, 100);
  206.    gtk_signal_connect(GTK_OBJECT(data->height), "changed", 
  207.               (GtkSignalFunc) height_changed_cb, (gpointer) data);
  208.    create_label_in_table(table, 1, 2, _("pixels"));
  209.  
  210.    gtk_widget_show(table);
  211.    gtk_widget_show(frame);
  212.    
  213.    data->offset_frame = frame = gtk_frame_new(_("Grid Offset"));
  214.    gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 1, 2, 2, 3);
  215.    table = gtk_table_new(2, 2, FALSE);
  216.    gtk_container_set_border_width(GTK_CONTAINER(table), 10);
  217.    gtk_table_set_row_spacings(GTK_TABLE(table), 10);
  218.    gtk_table_set_col_spacings(GTK_TABLE(table), 10);
  219.    gtk_container_add(GTK_CONTAINER(frame), table);
  220.  
  221.    data->left = create_spin_button_in_table(table, 0, 0, 0, 0, 100);
  222.    gtk_signal_connect(GTK_OBJECT(data->left), "changed", 
  223.               (GtkSignalFunc) left_changed_cb, (gpointer) data);
  224.    create_label_in_table(table, 0, 1, _("pixels from left"));
  225.  
  226.    data->top = create_spin_button_in_table(table, 1, 0, 0, 0, 100);
  227.    gtk_signal_connect(GTK_OBJECT(data->top), "changed", 
  228.               (GtkSignalFunc) top_changed_cb, (gpointer) data);
  229.    create_label_in_table(table, 1, 1, _("pixels from top"));
  230.  
  231.    data->preview = create_check_button_in_table(main_table, 3, 0, 
  232.                         _("Preview"));
  233.    gtk_signal_connect(GTK_OBJECT(data->preview), "toggled", 
  234.               (GtkSignalFunc) toggle_preview_cb, (gpointer) data);
  235.    gtk_widget_show(data->preview);
  236.  
  237.    snap_toggled_cb(data->snap, data);
  238.  
  239.    gtk_widget_show(table);
  240.    gtk_widget_show(frame);
  241.  
  242.    return data;
  243. }
  244.  
  245. void
  246. do_grid_settings_dialog(void)
  247. {
  248.    static GridDialog_t* dialog;
  249.    GtkWidget *type;
  250.  
  251.    if (!dialog)
  252.       dialog = create_grid_settings_dialog();
  253.  
  254.    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->snap), grid_snap);
  255.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->width), grid_width);
  256.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->height), grid_height);
  257.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->left), grid_left);
  258.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->top), grid_top);
  259.  
  260.    if (grid_type == GRID_HIDDEN)
  261.       type = dialog->hidden;
  262.    else if (grid_type == GRID_LINES)
  263.       type = dialog->lines;
  264.    else
  265.       type = dialog->crosses;
  266.    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(type), TRUE);
  267.  
  268.    default_dialog_show(dialog->dialog);
  269. }
  270.  
  271. static void
  272. draw_lines(GdkWindow *window, GdkGC* gc, gint width, gint height)
  273. {
  274.    gint x, y;
  275.  
  276.    for (x = grid_left; x < width; x += grid_width)
  277.       draw_line(window, grid_gc, x, 1, x, height);
  278.    for (y = grid_top; y < height; y += grid_height)
  279.       draw_line(window, grid_gc, 1, y, width, y);
  280. }
  281.  
  282. static void
  283. draw_crosses(GdkWindow *window, GdkGC* gc, gint width, gint height)
  284. {
  285.    gint x, y;
  286.  
  287.    for (x = grid_left; x < width; x += grid_width) {
  288.       for (y = grid_top; y < height; y += grid_height) {
  289.      draw_line(window, gc, x - 3, y, x + 3, y);
  290.      draw_line(window, gc, x, y - 3, x, y + 3);     
  291.       }
  292.    }
  293. }
  294.  
  295. void
  296. draw_grid(GtkWidget *preview)
  297. {
  298.    if (grid_snap && grid_type != GRID_HIDDEN) {
  299.       gint width = preview_get_width(preview);
  300.       gint height = preview_get_height(preview);
  301.       
  302.       if (!grid_gc) {
  303.      grid_gc = gdk_gc_new(preview->window);
  304.      gdk_gc_set_line_attributes(grid_gc, 1, GDK_LINE_ON_OFF_DASH,
  305.                     GDK_CAP_BUTT, GDK_JOIN_BEVEL);
  306.       }
  307.       if (grid_type == GRID_LINES)
  308.      draw_lines(preview->window, grid_gc, width, height);
  309.       else
  310.      draw_crosses(preview->window, preview->style->black_gc, width, 
  311.               height);
  312.    }
  313. }
  314.  
  315. gboolean
  316. toggle_grid(void)
  317. {
  318.    grid_snap = !grid_snap;
  319.    redraw_preview();
  320.    return grid_snap;
  321. }
  322.  
  323. static gint
  324. grid_nearest_x(gint x)
  325. {
  326.    return grid_left + (x - grid_left + grid_width / 2) / grid_width 
  327.       * grid_width;
  328. }
  329.  
  330. static gint
  331. grid_nearest_y(gint y)
  332. {
  333.    return grid_top + (y - grid_top + grid_height / 2) / grid_height 
  334.       * grid_height;
  335. }
  336.  
  337. void 
  338. round_to_grid(gint *x, gint *y)
  339. {
  340.    if (grid_snap) {
  341.       *x = grid_nearest_x(*x);
  342.       *y = grid_nearest_y(*y);
  343.    }
  344. }
  345.  
  346. gboolean
  347. grid_near_x(gint x)
  348. {
  349.    return grid_snap && grid_type != GRID_HIDDEN 
  350.       && abs(grid_nearest_x(x) - x) <= 1;
  351. }
  352.  
  353. gboolean
  354. grid_near_y(gint y)
  355. {
  356.    return grid_snap && grid_type != GRID_HIDDEN 
  357.       && abs(grid_nearest_x(y) - y) <= 1;
  358. }
  359.