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_selection.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-23  |  13.2 KB  |  431 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 <stdio.h>
  25.  
  26. #include "config.h"
  27. #include "imap_cmd_edit_object.h"
  28. #include "imap_cmd_select.h"
  29. #include "imap_cmd_unselect.h"
  30. #include "imap_cmd_unselect_all.h"
  31. #include "imap_edit_area_info.h"
  32. #include "libgimp/stdplugins-intl.h"
  33. #include "imap_main.h"
  34. #include "imap_misc.h"
  35. #include "imap_selection.h"
  36.  
  37. #include "arrow_up.xpm"
  38. #include "arrow_down.xpm"
  39. #include "delete.xpm"
  40. #include "edit.xpm"
  41.  
  42. static void
  43. set_buttons(Selection_t *data)
  44. {
  45.    if (data->selected_child) {
  46.       gtk_widget_set_sensitive(data->arrow_up, 
  47.                    (data->selected_row) ? TRUE : FALSE);
  48.       if (data->selected_row < GTK_CLIST(data->list)->rows - 1) 
  49.      gtk_widget_set_sensitive(data->arrow_down, TRUE);
  50.       else
  51.      gtk_widget_set_sensitive(data->arrow_down, FALSE);
  52.       gtk_widget_set_sensitive(data->remove, TRUE);
  53.       gtk_widget_set_sensitive(data->edit, TRUE);
  54.    } else {
  55.       gtk_widget_set_sensitive(data->arrow_up, FALSE);
  56.       gtk_widget_set_sensitive(data->arrow_down, FALSE);
  57.       gtk_widget_set_sensitive(data->remove, FALSE);
  58.       gtk_widget_set_sensitive(data->edit, FALSE);
  59.    }
  60. }
  61.  
  62. static void
  63. select_row_cb(GtkWidget *widget, gint row, gint column, GdkEventButton *event,
  64.           Selection_t *data)
  65. {
  66.    data->selected_child = widget;
  67.    data->selected_row = row;
  68.  
  69.    set_buttons(data);
  70.    if (data->select_lock) {
  71.       data->select_lock = FALSE;
  72.    } else {
  73.       Object_t *obj = gtk_clist_get_row_data(GTK_CLIST(data->list), row);
  74.       Command_t *command;
  75.       /* Note: event can be NULL if select_row_cb is called as a result of
  76.      a key press! */
  77.       if (event && event->state & GDK_SHIFT_MASK) {
  78.      command = select_command_new(obj);
  79.       } else {
  80.      Command_t *sub_command;
  81.      
  82.      command = subcommand_start(NULL);
  83.      sub_command = unselect_all_command_new(data->object_list, NULL);
  84.      command_add_subcommand(command, sub_command);
  85.      sub_command = select_command_new(obj);
  86.      command_add_subcommand(command, sub_command);
  87.      command_set_name(command, sub_command->name);
  88.      subcommand_end();
  89.       }
  90.       command_execute(command);
  91.       redraw_preview();        /* Fix me! */
  92.    }
  93. }
  94.  
  95. static void
  96. unselect_row_cb(GtkWidget *widget, gint row, gint column, 
  97.         GdkEventButton *event, Selection_t *data)
  98. {
  99.    if (data->unselect_lock) {
  100.       data->unselect_lock = FALSE;
  101.    } else {
  102.       Object_t *obj = gtk_clist_get_row_data(GTK_CLIST(data->list), row);
  103.       Command_t *command;
  104.       command = unselect_command_new(obj);
  105.       command_execute(command);
  106.       redraw_preview();        /* Fix me! */
  107.    }
  108.    data->selected_child = NULL;
  109.    set_buttons(data);
  110. }
  111.  
  112. static void
  113. row_move_cb(GtkWidget *widget, gint src, gint des)
  114. {
  115.    printf("move: %d %d\n", src, des);
  116. }
  117.  
  118. static gboolean doubleclick;
  119.  
  120. static void
  121. button_press_cb(GtkWidget *widget, GdkEventButton *event, Selection_t *data)
  122. {
  123.    if (event->button == 1) {
  124.       if (doubleclick) {
  125.      gint row, column;
  126.      doubleclick = FALSE;
  127.      if (gtk_clist_get_selection_info(GTK_CLIST(widget), (gint) event->x, 
  128.                       (gint) event->y, &row, &column)) {
  129.         Object_t *obj = gtk_clist_get_row_data(GTK_CLIST(data->list), row);
  130.         object_edit(obj, TRUE);
  131.      }
  132.       } else {
  133.      doubleclick = TRUE;
  134.       }
  135.    }
  136. }
  137.  
  138. static void
  139. button_release_cb(GtkWidget *widget, GdkEventButton *event, gpointer data)
  140. {
  141.    if (event->button == 1)
  142.       doubleclick = FALSE;
  143. }
  144.  
  145. static void
  146. selection_command(GtkWidget *widget, gpointer data)
  147. {
  148.    CommandFactory_t *factory = (CommandFactory_t*) data;
  149.    Command_t *command = (*factory)();
  150.    command_execute(command);
  151. }
  152.  
  153. static GtkWidget*
  154. make_selection_toolbar(Selection_t *data, GtkWidget *window)
  155. {
  156.    GtkWidget *toolbar;
  157.  
  158.    toolbar = gtk_toolbar_new(GTK_ORIENTATION_VERTICAL, GTK_TOOLBAR_ICONS);
  159.    gtk_container_set_border_width(GTK_CONTAINER(toolbar), 5);
  160.    gtk_toolbar_set_space_size(GTK_TOOLBAR(toolbar), 5);
  161.  
  162.    data->arrow_up = make_toolbar_icon(toolbar, window, arrow_up_xpm, "MoveUp",
  163.                       _("Move Up"), selection_command, 
  164.                       &data->cmd_move_up);
  165.    data->arrow_down = make_toolbar_icon(toolbar, window, arrow_down_xpm, 
  166.                     "MoveDown", _("Move Down"), 
  167.                     selection_command, 
  168.                     &data->cmd_move_down);
  169.    gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
  170.    data->edit = make_toolbar_icon(toolbar, window, edit_xpm, "Edit",
  171.                   _("Edit"), selection_command, 
  172.                   &data->cmd_edit);
  173.    gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
  174.    data->remove = make_toolbar_icon(toolbar, window, delete_xpm, "Delete",
  175.                     _("Delete"), selection_command, 
  176.                     &data->cmd_delete);
  177.  
  178.    gtk_widget_show(toolbar);
  179.  
  180.    return toolbar;
  181. }
  182.  
  183. static void
  184. selection_update(Selection_t *selection, gint row, Object_t *obj)
  185. {
  186.    GdkBitmap *mask;
  187.    GdkPixmap *icon = object_get_icon(obj, selection->list, &mask);
  188.  
  189.    gtk_clist_set_pixtext(GTK_CLIST(selection->list), row, 1, obj->url, 8,
  190.              icon, mask);
  191.    gtk_clist_set_text(GTK_CLIST(selection->list), row, 2, obj->target);
  192.    gtk_clist_set_text(GTK_CLIST(selection->list), row, 3, obj->comment);
  193. }
  194.  
  195. static void
  196. selection_renumber(Selection_t *selection, gint row)
  197. {
  198.    for (; row < selection->nr_rows; row++) {
  199.       char scratch[16];
  200.       sprintf(scratch, "%d", row + 1);
  201.       gtk_clist_set_text(GTK_CLIST(selection->list), row, 0, scratch);
  202.    }
  203. }
  204.  
  205. static void
  206. selection_set_selected(Selection_t *selection, gint row)
  207. {
  208.    Object_t *obj = gtk_clist_get_row_data(GTK_CLIST(selection->list), row);
  209.  
  210.    if (obj->selected) {
  211.       selection->select_lock = TRUE;
  212.       gtk_clist_select_row(GTK_CLIST(selection->list), row, -1);
  213.    } else {
  214.       selection->unselect_lock = TRUE;
  215.       gtk_clist_unselect_row(GTK_CLIST(selection->list), row, -1);
  216.    }
  217. }
  218.  
  219. static void
  220. object_added_cb(Object_t *obj, gpointer data)
  221. {
  222.    Selection_t *selection = (Selection_t*) data;
  223.    gint row = object_get_position_in_list(obj);
  224.    char scratch[16];
  225.    gchar *text[4];
  226.  
  227.    selection->nr_rows++;
  228.    
  229.    text[0] = scratch;
  230.    text[1] = obj->url;
  231.    text[2] = obj->target;
  232.    text[3] = obj->comment;
  233.    
  234.    if (row < selection->nr_rows - 1) {
  235.       sprintf(scratch, "%d", row + 1);
  236.       gtk_clist_insert(GTK_CLIST(selection->list), row, text);
  237.       selection_renumber(selection, row);
  238.    } else {
  239.       sprintf(scratch, "%d", selection->nr_rows);
  240.       gtk_clist_append(GTK_CLIST(selection->list), text);
  241.    }
  242.    selection_update(selection, row, obj);
  243.    gtk_clist_set_row_data(GTK_CLIST(selection->list), row, (gpointer) obj);
  244.    selection_set_selected(selection, row);
  245. }
  246.  
  247. static gint
  248. selection_find_object(Selection_t *selection, Object_t *obj)
  249. {
  250.    return gtk_clist_find_row_from_data(GTK_CLIST(selection->list),
  251.                        (gpointer) obj);
  252. }
  253.  
  254. static void
  255. object_updated_cb(Object_t *obj, gpointer data)
  256. {
  257.    Selection_t *selection = (Selection_t*) data;
  258.    gint row = selection_find_object(selection, obj);
  259.    selection_update(selection, row, obj);
  260. }
  261.  
  262. static void
  263. object_removed_cb(Object_t *obj, gpointer data)
  264. {
  265.    Selection_t *selection = (Selection_t*) data;
  266.    gint row = selection_find_object(selection, obj);
  267.  
  268.    selection->unselect_lock = TRUE;
  269.    gtk_clist_unselect_row(GTK_CLIST(selection->list), row, -1);
  270.    gtk_clist_remove(GTK_CLIST(selection->list), row);
  271.    selection_renumber(selection, row);
  272.    selection->selected_child = NULL;
  273.    selection->nr_rows--;
  274.    set_buttons(selection);
  275. }
  276.  
  277. static void
  278. object_selected_cb(Object_t *obj, gpointer data)
  279. {
  280.    Selection_t *selection = (Selection_t*) data;
  281.    gint row = selection_find_object(selection, obj);
  282.  
  283.    selection_set_selected(selection, row);
  284. }
  285.  
  286. static void
  287. object_moved_cb(Object_t *obj, gpointer data)
  288. {
  289.    Selection_t *selection = (Selection_t*) data;
  290.    gint row = object_get_position_in_list(obj);
  291.    selection->select_lock = TRUE;
  292.    gtk_clist_set_row_data(GTK_CLIST(selection->list), row, (gpointer) obj);
  293.    selection_set_selected(selection, row);
  294.    selection_update(selection, row, obj);
  295. }
  296.  
  297. static void
  298. toggle_order(GtkWidget *widget, gint column, gpointer data)
  299. {
  300.    /* Fix me! */
  301. }
  302.  
  303. static GtkTargetEntry target_table[] = {
  304.    {"STRING", 0, 1 },
  305.    {"text/plain", 0, 2 }
  306. };
  307.  
  308. static void 
  309. handle_drop(GtkWidget *widget, GdkDragContext *context, gint x, gint y, 
  310.         GtkSelectionData *data, guint info, guint time)
  311. {
  312.    gboolean success = FALSE;
  313.    if (data->length >= 0 && data->format == 8) {
  314.       gint row, column;
  315.       if (gtk_clist_get_selection_info(GTK_CLIST(widget), x, y, &row, 
  316.                        &column)) {
  317.      Object_t *obj = gtk_clist_get_row_data(GTK_CLIST(widget), row + 1);
  318.      if (!obj->locked) {
  319.         command_list_add(edit_object_command_new(obj));
  320.         object_set_url(obj, data->data);
  321.         object_emit_update_signal(obj);
  322.         success = TRUE;
  323.      }
  324.       }
  325.    }
  326.    gtk_drag_finish(context, success, FALSE, time);
  327. }
  328.  
  329. Selection_t*
  330. make_selection(GtkWidget *window, ObjectList_t *object_list)
  331. {
  332.    Selection_t *data = g_new(Selection_t, 1);
  333.    GtkWidget *swin, *frame, *hbox;
  334.    GtkWidget *toolbar;
  335.    GtkWidget *list;
  336.    gchar     *titles[] = {"#", N_("URL"), N_("Target"), N_("Comment")};
  337.    gint      i;
  338.  
  339.    data->object_list = object_list;
  340.    data->selected_child = NULL;
  341.    data->is_visible = TRUE;
  342.    data->nr_rows = 0;
  343.    data->select_lock = FALSE;
  344.    data->unselect_lock = FALSE;
  345.  
  346.    data->container = frame = gtk_frame_new(NULL);
  347.    gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
  348.    gtk_widget_show(frame);
  349.  
  350.    hbox = gtk_hbox_new(FALSE, 1);
  351.    gtk_container_add(GTK_CONTAINER(frame), hbox); 
  352.    gtk_widget_show(hbox);
  353.  
  354.    toolbar = make_selection_toolbar(data, window);
  355.    gtk_container_add(GTK_CONTAINER(hbox), toolbar);
  356.  
  357.    /* Create selection */
  358.    frame = gtk_frame_new(_("Selection"));
  359.    gtk_container_set_border_width(GTK_CONTAINER(frame), 10);
  360.    gtk_container_add(GTK_CONTAINER(hbox), frame);
  361.    gtk_widget_show(frame);
  362.  
  363.    for (i = 0; i < 4; i++)
  364.      titles[i] = gettext(titles[i]);
  365.    data->list = list = gtk_clist_new_with_titles(4, titles);
  366.    GTK_WIDGET_UNSET_FLAGS(data->list, GTK_CAN_FOCUS);
  367.    gtk_clist_column_titles_passive(GTK_CLIST(list));
  368.    gtk_clist_column_title_active(GTK_CLIST(list), 0);
  369.    gtk_clist_set_column_width(GTK_CLIST(list), 0, 16);
  370.    gtk_clist_set_column_width(GTK_CLIST(list), 1, 80);
  371.    gtk_clist_set_column_width(GTK_CLIST(list), 2, 64);
  372.    gtk_clist_set_column_width(GTK_CLIST(list), 3, 64);
  373. /*   gtk_clist_set_reorderable(GTK_CLIST(list), TRUE); */
  374.  
  375.    /* Create scrollable window */
  376.    swin = gtk_scrolled_window_new(NULL, NULL);
  377.    gtk_widget_set_usize(swin, 16 + 80 + 2 * 64 + 16, -1);
  378.    gtk_container_add(GTK_CONTAINER(frame), swin);
  379.    gtk_widget_show(swin);
  380.  
  381.    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), list);
  382.    gtk_widget_show(list);
  383.  
  384.    /* Drop support */
  385.    gtk_drag_dest_set(list, GTK_DEST_DEFAULT_ALL, target_table,
  386.              2, GDK_ACTION_COPY);
  387.    gtk_signal_connect(GTK_OBJECT(list), "drag_data_received",
  388.               GTK_SIGNAL_FUNC(handle_drop), NULL);
  389.  
  390.    /* Callbacks we are interested in */
  391.    gtk_signal_connect(GTK_OBJECT(list), "click_column",
  392.               GTK_SIGNAL_FUNC(toggle_order), data);
  393.    gtk_signal_connect(GTK_OBJECT(list), "select_row",
  394.               GTK_SIGNAL_FUNC(select_row_cb), data);
  395.    gtk_signal_connect(GTK_OBJECT(list), "unselect_row",
  396.               GTK_SIGNAL_FUNC(unselect_row_cb), data);
  397.    gtk_signal_connect(GTK_OBJECT(list), "row_move",
  398.               GTK_SIGNAL_FUNC(row_move_cb), data);
  399.  
  400.    /* For handling doubleclick */
  401.    gtk_signal_connect(GTK_OBJECT(list), "button_press_event",
  402.               GTK_SIGNAL_FUNC(button_press_cb), data);
  403.    gtk_signal_connect(GTK_OBJECT(list), "button_release_event",
  404.               GTK_SIGNAL_FUNC(button_release_cb), data);
  405.  
  406.    gtk_clist_set_selection_mode(GTK_CLIST(list), GTK_SELECTION_MULTIPLE);
  407.  
  408.    set_buttons(data);
  409.  
  410.    /* Set object list callbacks we're interested in */
  411.    object_list_add_add_cb(object_list, object_added_cb, data);
  412.    object_list_add_update_cb(object_list, object_updated_cb, data);
  413.    object_list_add_remove_cb(object_list, object_removed_cb, data);
  414.    object_list_add_select_cb(object_list, object_selected_cb, data);
  415.    object_list_add_move_cb(object_list, object_moved_cb, data);
  416.  
  417.    return data;
  418. }
  419.  
  420. void
  421. selection_toggle_visibility(Selection_t *selection)
  422. {
  423.    if (selection->is_visible) {
  424.       gtk_widget_hide(selection->container);
  425.       selection->is_visible = FALSE;
  426.    } else {
  427.       gtk_widget_show(selection->container);
  428.       selection->is_visible = TRUE;
  429.    }
  430. }
  431.