home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / gimpdnd.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-01  |  32.7 KB  |  1,282 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18. #include <string.h>
  19.  
  20. #include "fileops.h"
  21. #include "gimage.h"
  22. #include "gimpcontextpreview.h"
  23. #include "gimpdnd.h"
  24. #include "gimpbrushlist.h"
  25. #include "gimprc.h"
  26. #include "gradient_header.h"
  27. #include "tools.h"
  28.  
  29. #include "libgimp/gimplimits.h"
  30.  
  31. #define DRAG_PREVIEW_SIZE 32
  32.  
  33. #define DRAG_ICON_OFFSET  -8
  34.  
  35. typedef enum
  36. {
  37.   GIMP_DND_DATA_COLOR = 1,
  38.   GIMP_DND_DATA_BRUSH,
  39.   GIMP_DND_DATA_PATTERN,
  40.   GIMP_DND_DATA_GRADIENT,
  41.   GIMP_DND_DATA_PALETTE,
  42.   GIMP_DND_DATA_TOOL,
  43.   GIMP_DND_DATA_LAST = GIMP_DND_DATA_TOOL
  44. } GimpDndDataType;
  45.  
  46. typedef GtkWidget * (* GimpDndGetIconFunc)  (GtkWidget     *widget,
  47.                          GtkSignalFunc  get_data_func,
  48.                          gpointer       get_data_data);
  49. typedef guchar    * (* GimpDndDragDataFunc) (GtkWidget     *widget,
  50.                          GtkSignalFunc  get_data_func,
  51.                          gpointer       get_data_data,
  52.                          gint          *format,
  53.                          gint          *length);
  54. typedef void        (* GimpDndDropDataFunc) (GtkWidget     *widget,
  55.                          GtkSignalFunc  set_data_func,
  56.                          gpointer       set_data_data,
  57.                          guchar        *vals,
  58.                          gint           format,
  59.                          gint           length);
  60.  
  61. typedef struct _GimpDndDataDef GimpDndDataDef;
  62.  
  63. struct _GimpDndDataDef
  64. {
  65.   GtkTargetEntry       target_entry;
  66.  
  67.   gchar               *set_data_func_name;
  68.   gchar               *set_data_data_name;
  69.  
  70.   GimpDndGetIconFunc   get_icon_func;
  71.   GimpDndDragDataFunc  get_data_func;
  72.   GimpDndDropDataFunc  set_data_func;
  73. };
  74.  
  75. static GtkWidget * gimp_dnd_get_color_icon    (GtkWidget     *widget,
  76.                            GtkSignalFunc  get_color_func,
  77.                            gpointer       get_color_data);
  78. static GtkWidget * gimp_dnd_get_brush_icon    (GtkWidget     *widget,
  79.                            GtkSignalFunc  get_brush_func,
  80.                            gpointer       get_brush_data);
  81. static GtkWidget * gimp_dnd_get_pattern_icon  (GtkWidget     *widget,
  82.                            GtkSignalFunc  get_pattern_func,
  83.                            gpointer       get_pattern_data);
  84. static GtkWidget * gimp_dnd_get_gradient_icon (GtkWidget     *widget,
  85.                            GtkSignalFunc  get_gradient_func,
  86.                            gpointer       get_gradient_data);
  87. static GtkWidget * gimp_dnd_get_palette_icon  (GtkWidget     *widget,
  88.                            GtkSignalFunc  get_gradient_func,
  89.                            gpointer       get_gradient_data);
  90. static GtkWidget * gimp_dnd_get_tool_icon     (GtkWidget     *widget,
  91.                            GtkSignalFunc  get_tool_func,
  92.                            gpointer       get_tool_data);
  93.  
  94. static guchar    * gimp_dnd_get_color_data    (GtkWidget     *widget,
  95.                            GtkSignalFunc  get_color_func,
  96.                            gpointer       get_color_data,
  97.                            gint          *format,
  98.                            gint          *length);
  99. static guchar    * gimp_dnd_get_brush_data    (GtkWidget     *widget,
  100.                            GtkSignalFunc  get_brush_func,
  101.                            gpointer       get_brush_data,
  102.                            gint          *format,
  103.                            gint          *length);
  104. static guchar    * gimp_dnd_get_pattern_data  (GtkWidget     *widget,
  105.                            GtkSignalFunc  get_pattern_func,
  106.                            gpointer       get_pattern_data,
  107.                            gint          *format,
  108.                            gint          *length);
  109. static guchar    * gimp_dnd_get_gradient_data (GtkWidget     *widget,
  110.                            GtkSignalFunc  get_gradient_func,
  111.                            gpointer       get_gradient_data,
  112.                            gint          *format,
  113.                            gint          *length);
  114. static guchar    * gimp_dnd_get_palette_data  (GtkWidget     *widget,
  115.                            GtkSignalFunc  get_gradient_func,
  116.                            gpointer       get_gradient_data,
  117.                            gint          *format,
  118.                            gint          *length);
  119. static guchar    * gimp_dnd_get_tool_data     (GtkWidget     *widget,
  120.                            GtkSignalFunc  get_tool_func,
  121.                            gpointer       get_tool_data,
  122.                            gint          *format,
  123.                            gint          *length);
  124.  
  125. static void        gimp_dnd_set_color_data    (GtkWidget     *widget,
  126.                            GtkSignalFunc  set_color_func,
  127.                            gpointer       set_color_data,
  128.                            guchar        *vals,
  129.                            gint           format,
  130.                            gint           length);
  131. static void        gimp_dnd_set_brush_data    (GtkWidget     *widget,
  132.                            GtkSignalFunc  set_brush_func,
  133.                            gpointer       set_brush_data,
  134.                            guchar        *vals,
  135.                            gint           format,
  136.                            gint           length);
  137. static void        gimp_dnd_set_pattern_data  (GtkWidget     *widget,
  138.                            GtkSignalFunc  set_pattern_func,
  139.                            gpointer       set_pattern_data,
  140.                            guchar        *vals,
  141.                            gint           format,
  142.                            gint           length);
  143. static void        gimp_dnd_set_gradient_data (GtkWidget     *widget,
  144.                            GtkSignalFunc  set_gradient_func,
  145.                            gpointer       set_gradient_data,
  146.                            guchar        *vals,
  147.                            gint           format,
  148.                            gint           length);
  149. static void        gimp_dnd_set_palette_data  (GtkWidget     *widget,
  150.                            GtkSignalFunc  set_gradient_func,
  151.                            gpointer       set_gradient_data,
  152.                            guchar        *vals,
  153.                            gint           format,
  154.                            gint           length);
  155. static void        gimp_dnd_set_tool_data     (GtkWidget     *widget,
  156.                            GtkSignalFunc  set_tool_func,
  157.                            gpointer       set_tool_data,
  158.                            guchar        *vals,
  159.                            gint           format,
  160.                            gint           length);
  161.  
  162. static GimpDndDataDef dnd_data_defs[] =
  163. {
  164.   {
  165.     { NULL, 0, -1 },
  166.  
  167.     NULL,
  168.     NULL,
  169.  
  170.     NULL,
  171.     NULL,
  172.     NULL
  173.   },
  174.  
  175.   {
  176.     GIMP_TARGET_COLOR,
  177.  
  178.     "gimp_dnd_set_color_func",
  179.     "gimp_dnd_set_color_data",
  180.  
  181.     gimp_dnd_get_color_icon,
  182.     gimp_dnd_get_color_data,
  183.     gimp_dnd_set_color_data
  184.   },
  185.  
  186.   {
  187.     GIMP_TARGET_BRUSH,
  188.  
  189.     "gimp_dnd_set_brush_func",
  190.     "gimp_dnd_set_brush_data",
  191.  
  192.     gimp_dnd_get_brush_icon,
  193.     gimp_dnd_get_brush_data,
  194.     gimp_dnd_set_brush_data
  195.   },
  196.  
  197.   {
  198.     GIMP_TARGET_PATTERN,
  199.  
  200.     "gimp_dnd_set_pattern_func",
  201.     "gimp_dnd_set_pattern_data",
  202.  
  203.     gimp_dnd_get_pattern_icon,
  204.     gimp_dnd_get_pattern_data,
  205.     gimp_dnd_set_pattern_data
  206.   },
  207.  
  208.   {
  209.     GIMP_TARGET_GRADIENT,
  210.  
  211.     "gimp_dnd_set_gradient_func",
  212.     "gimp_dnd_set_gradient_data",
  213.  
  214.     gimp_dnd_get_gradient_icon,
  215.     gimp_dnd_get_gradient_data,
  216.     gimp_dnd_set_gradient_data
  217.   },
  218.  
  219.   {
  220.     GIMP_TARGET_PALETTE,
  221.  
  222.     "gimp_dnd_set_palette_func",
  223.     "gimp_dnd_set_palette_data",
  224.  
  225.     gimp_dnd_get_palette_icon,
  226.     gimp_dnd_get_palette_data,
  227.     gimp_dnd_set_palette_data
  228.   },
  229.  
  230.   {
  231.     GIMP_TARGET_TOOL,
  232.  
  233.     "gimp_dnd_set_tool_func",
  234.     "gimp_dnd_set_tool_data",
  235.  
  236.     gimp_dnd_get_tool_icon,
  237.     gimp_dnd_get_tool_data,
  238.     gimp_dnd_set_tool_data
  239.   }
  240. };
  241.  
  242. /********************************/
  243. /*  general data dnd functions  */
  244. /********************************/
  245.  
  246. static void
  247. gimp_dnd_data_drag_begin (GtkWidget      *widget,
  248.               GdkDragContext *context,
  249.               gpointer        data)
  250. {
  251.   GimpDndDataType data_type;
  252.   GtkSignalFunc   get_data_func;
  253.   gpointer        get_data_data;
  254.   GtkWidget      *icon_widget;
  255.  
  256.   data_type =
  257.     (GimpDndDataType) gtk_object_get_data (GTK_OBJECT (widget),
  258.                        "gimp_dnd_get_data_type");
  259.  
  260.   if (! data_type)
  261.     return;
  262.  
  263.   get_data_func =
  264.     (GtkSignalFunc) gtk_object_get_data (GTK_OBJECT (widget),
  265.                      "gimp_dnd_get_data_func");
  266.   get_data_data =
  267.     (gpointer) gtk_object_get_data (GTK_OBJECT (widget),
  268.                     "gimp_dnd_get_data_data");
  269.  
  270.   if (! get_data_func)
  271.     return;
  272.  
  273.   icon_widget = (* dnd_data_defs[data_type].get_icon_func) (widget,
  274.                                 get_data_func,
  275.                                 get_data_data);
  276.  
  277.   if (icon_widget)
  278.     {
  279.       GtkWidget *frame;
  280.       GtkWidget *window;
  281.  
  282.       window = gtk_window_new (GTK_WINDOW_POPUP);
  283.       gtk_widget_realize (window);
  284.  
  285.       frame = gtk_frame_new (NULL);
  286.       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
  287.       gtk_container_add (GTK_CONTAINER (window), frame);
  288.       gtk_widget_show (frame);
  289.  
  290.       gtk_container_add (GTK_CONTAINER (frame), icon_widget);
  291.       gtk_widget_show (icon_widget);
  292.  
  293.       gtk_object_set_data_full (GTK_OBJECT (widget),
  294.                 "gimp-dnd-data-widget",
  295.                 window,
  296.                 (GtkDestroyNotify) gtk_widget_destroy);
  297.  
  298.       gtk_drag_set_icon_widget (context, window,
  299.                 DRAG_ICON_OFFSET, DRAG_ICON_OFFSET);
  300.     }
  301. }
  302.  
  303. static void
  304. gimp_dnd_data_drag_end (GtkWidget      *widget,
  305.             GdkDragContext *context)
  306. {
  307.   gtk_object_set_data (GTK_OBJECT (widget),
  308.                "gimp-dnd-data-widget", NULL);
  309. }
  310.  
  311. static void
  312. gimp_dnd_data_drag_handle (GtkWidget        *widget, 
  313.                GdkDragContext   *context,
  314.                GtkSelectionData *selection_data,
  315.                guint             info,
  316.                guint             time,
  317.                gpointer          data)
  318. {
  319.   GimpDndDataType data_type;
  320.   GtkSignalFunc   get_data_func;
  321.   gpointer        get_data_data;
  322.   gint    format;
  323.   guchar *vals;
  324.   gint    length;
  325.  
  326.   data_type =
  327.     (GimpDndDataType) gtk_object_get_data (GTK_OBJECT (widget),
  328.                        "gimp_dnd_get_data_type");
  329.  
  330.   if (! data_type)
  331.     return;
  332.  
  333.   get_data_func =
  334.     (GtkSignalFunc) gtk_object_get_data (GTK_OBJECT (widget),
  335.                      "gimp_dnd_get_data_func");
  336.   get_data_data =
  337.     (gpointer) gtk_object_get_data (GTK_OBJECT (widget),
  338.                     "gimp_dnd_get_data_data");
  339.  
  340.   if (! get_data_func)
  341.     return;
  342.  
  343.   vals = (* dnd_data_defs[data_type].get_data_func) (widget,
  344.                              get_data_func,
  345.                              get_data_data,
  346.                              &format,
  347.                              &length);
  348.  
  349.   if (vals)
  350.     {
  351.       gtk_selection_data_set
  352.     (selection_data,
  353.      gdk_atom_intern (dnd_data_defs[data_type].target_entry.target, FALSE),
  354.      format, vals, length);
  355.  
  356.       g_free (vals);
  357.     }
  358. }
  359.  
  360. static void
  361. gimp_dnd_data_drop_handle (GtkWidget        *widget, 
  362.                GdkDragContext   *context,
  363.                gint              x,
  364.                gint              y,
  365.                GtkSelectionData *selection_data,
  366.                guint             info,
  367.                guint             time,
  368.                gpointer          data)
  369. {
  370.   GtkSignalFunc   set_data_func;
  371.   gpointer        set_data_data;
  372.   GimpDndDataType data_type;
  373.  
  374.   if (selection_data->length < 0)
  375.     return;
  376.  
  377.   for (data_type = GIMP_DND_DATA_COLOR;
  378.        data_type <= GIMP_DND_DATA_LAST;
  379.        data_type++)
  380.     {
  381.       if (dnd_data_defs[data_type].target_entry.info == info)
  382.     {
  383.       set_data_func = (GtkSignalFunc)
  384.         gtk_object_get_data (GTK_OBJECT (widget),
  385.                  dnd_data_defs[data_type].set_data_func_name);
  386.       set_data_data = (gpointer)
  387.         gtk_object_get_data (GTK_OBJECT (widget),
  388.                  dnd_data_defs[data_type].set_data_data_name);
  389.  
  390.       if (! set_data_func)
  391.         return;
  392.  
  393.       (* dnd_data_defs[data_type].set_data_func) (widget,
  394.                               set_data_func,
  395.                               set_data_data,
  396.                               selection_data->data,
  397.                               selection_data->format,
  398.                               selection_data->length);
  399.  
  400.       return;
  401.     }
  402.     }
  403. }
  404.  
  405. static void
  406. gimp_dnd_data_source_set (GimpDndDataType  data_type,
  407.               GtkWidget       *widget,
  408.               GtkSignalFunc    get_data_func,
  409.               gpointer         get_data_data)
  410. {
  411.   gboolean drag_connected;
  412.  
  413.   drag_connected =
  414.     (gboolean) gtk_object_get_data (GTK_OBJECT (widget),
  415.                     "gimp_dnd_drag_connected");
  416.  
  417.   if (! drag_connected)
  418.     {
  419.       gtk_signal_connect (GTK_OBJECT (widget), "drag_begin",
  420.               GTK_SIGNAL_FUNC (gimp_dnd_data_drag_begin),
  421.               NULL);
  422.       gtk_signal_connect (GTK_OBJECT (widget), "drag_end",
  423.               GTK_SIGNAL_FUNC (gimp_dnd_data_drag_end),
  424.               NULL);
  425.       gtk_signal_connect (GTK_OBJECT (widget), "drag_data_get",
  426.               GTK_SIGNAL_FUNC (gimp_dnd_data_drag_handle),
  427.               NULL);
  428.  
  429.       gtk_object_set_data (GTK_OBJECT (widget), "gimp_dnd_drag_connected",
  430.                (gpointer) TRUE);
  431.     }
  432.  
  433.   gtk_object_set_data (GTK_OBJECT (widget), "gimp_dnd_get_data_type",
  434.                (gpointer) data_type);
  435.   gtk_object_set_data (GTK_OBJECT (widget), "gimp_dnd_get_data_func",
  436.                get_data_func);
  437.   gtk_object_set_data (GTK_OBJECT (widget), "gimp_dnd_get_data_data",
  438.                get_data_data);
  439. }
  440.  
  441. static void
  442. gimp_dnd_data_dest_set (GimpDndDataType  data_type,
  443.             GtkWidget       *widget,
  444.             gpointer         set_data_func,
  445.             gpointer         set_data_data)
  446. {
  447.   gboolean drop_connected;
  448.  
  449.   drop_connected =
  450.     (gboolean) gtk_object_get_data (GTK_OBJECT (widget),
  451.                     "gimp_dnd_drop_connected");
  452.  
  453.   if (! drop_connected)
  454.     {
  455.       gtk_signal_connect (GTK_OBJECT (widget), "drag_data_received",
  456.               GTK_SIGNAL_FUNC (gimp_dnd_data_drop_handle),
  457.               NULL);
  458.  
  459.       gtk_object_set_data (GTK_OBJECT (widget), "gimp_dnd_drop_connected",
  460.                (gpointer) TRUE);
  461.     }
  462.  
  463.   gtk_object_set_data (GTK_OBJECT (widget),
  464.                dnd_data_defs[data_type].set_data_func_name,
  465.                set_data_func);
  466.   gtk_object_set_data (GTK_OBJECT (widget),
  467.                dnd_data_defs[data_type].set_data_data_name,
  468.                set_data_data);
  469. }
  470.  
  471. /*************************/
  472. /*  color dnd functions  */
  473. /*************************/
  474.  
  475. static GtkWidget *
  476. gimp_dnd_get_color_icon (GtkWidget     *widget,
  477.              GtkSignalFunc  get_color_func,
  478.              gpointer       get_color_data)
  479. {
  480.   GtkWidget *preview;
  481.   guchar r, g, b;
  482.   guchar row[DRAG_PREVIEW_SIZE * 3];
  483.   gint   i;
  484.  
  485.   (* (GimpDndDragColorFunc) get_color_func) (widget, &r, &g, &b,
  486.                          get_color_data);
  487.  
  488.   for (i = 0; i < DRAG_PREVIEW_SIZE; i++)
  489.     {
  490.       row[i * 3]     = r;
  491.       row[i * 3 + 1] = g;
  492.       row[i * 3 + 2] = b;
  493.     }
  494.  
  495.   preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  496.   gtk_preview_size (GTK_PREVIEW (preview), 
  497.                     DRAG_PREVIEW_SIZE, DRAG_PREVIEW_SIZE);      
  498.  
  499.   for (i = 0; i < DRAG_PREVIEW_SIZE; i++)
  500.     {
  501.       gtk_preview_draw_row (GTK_PREVIEW (preview), row,
  502.                 0, i, DRAG_PREVIEW_SIZE);
  503.     }
  504.  
  505.   return preview;
  506. }
  507.  
  508. static guchar *
  509. gimp_dnd_get_color_data (GtkWidget     *widget,
  510.              GtkSignalFunc  get_color_func,
  511.              gpointer       get_color_data,
  512.              gint          *format,
  513.              gint          *length)
  514. {
  515.   guint16 *vals;
  516.   guchar r, g, b;
  517.  
  518.   (* (GimpDndDragColorFunc) get_color_func) (widget, &r, &g, &b,
  519.                          get_color_data);
  520.  
  521.   vals = g_new (guint16, 4);
  522.  
  523.   vals[0] = r + (r << 8);
  524.   vals[1] = g + (g << 8);
  525.   vals[2] = b + (b << 8);
  526.   vals[3] = 0xffff;
  527.  
  528.   *format = 16;
  529.   *length = 8;
  530.  
  531.   return (guchar *) vals;
  532. }
  533.  
  534. static void
  535. gimp_dnd_set_color_data (GtkWidget     *widget,
  536.              GtkSignalFunc  set_color_func,
  537.              gpointer       set_color_data,
  538.              guchar        *vals,
  539.              gint           format,
  540.              gint           length)
  541. {
  542.   guint16 *color_vals;
  543.   guchar r, g, b;
  544.  
  545.   if ((format != 16) || (length != 8))
  546.     {
  547.       g_warning ("Received invalid color data\n");
  548.       return;
  549.     }
  550.  
  551.   color_vals = (guint16 *) vals;
  552.  
  553.   r = color_vals[0] >> 8;
  554.   g = color_vals[1] >> 8;
  555.   b = color_vals[2] >> 8;
  556.  
  557.   (* (GimpDndDropColorFunc) set_color_func) (widget, r, g, b,
  558.                          set_color_data);
  559. }
  560.  
  561. void
  562. gimp_dnd_color_source_set (GtkWidget            *widget,
  563.                GimpDndDragColorFunc  get_color_func,
  564.                gpointer              data)
  565. {
  566.   gimp_dnd_data_source_set (GIMP_DND_DATA_COLOR, widget,
  567.                 GTK_SIGNAL_FUNC (get_color_func),
  568.                 data);
  569. }
  570.  
  571. void
  572. gimp_dnd_color_dest_set (GtkWidget            *widget,
  573.              GimpDndDropColorFunc  set_color_func,
  574.              gpointer              data)
  575. {
  576.   gimp_dnd_data_dest_set (GIMP_DND_DATA_COLOR, widget,
  577.               GTK_SIGNAL_FUNC (set_color_func),
  578.               data);
  579. }
  580.  
  581. /*************************/
  582. /*  brush dnd functions  */
  583. /*************************/
  584.  
  585. static GtkWidget *
  586. gimp_dnd_get_brush_icon (GtkWidget     *widget,
  587.              GtkSignalFunc  get_brush_func,
  588.              gpointer       get_brush_data)
  589. {
  590.   GtkWidget *preview;
  591.   GimpBrush *brush;
  592.  
  593.   brush = (* (GimpDndDragBrushFunc) get_brush_func) (widget, get_brush_data);
  594.  
  595.   if (! brush)
  596.     return NULL;
  597.  
  598.   preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  599.   gtk_preview_size (GTK_PREVIEW (preview), 
  600.                     DRAG_PREVIEW_SIZE, DRAG_PREVIEW_SIZE);      
  601.  
  602.   draw_brush (GTK_PREVIEW (preview), brush, 
  603.           DRAG_PREVIEW_SIZE, DRAG_PREVIEW_SIZE, FALSE);
  604.  
  605.   return preview;
  606. }
  607.  
  608. static guchar *
  609. gimp_dnd_get_brush_data (GtkWidget     *widget,
  610.              GtkSignalFunc  get_brush_func,
  611.              gpointer       get_brush_data,
  612.              gint          *format,
  613.              gint          *length)
  614. {
  615.   GimpBrush *brush;
  616.   gchar *name;
  617.  
  618.   brush = (* (GimpDndDragBrushFunc) get_brush_func) (widget, get_brush_data);
  619.  
  620.   if (! brush)
  621.     return NULL;
  622.  
  623.   name = g_strdup (gimp_brush_get_name (brush));
  624.  
  625.   if (! name)
  626.     return NULL;
  627.  
  628.   *format = 8;
  629.   *length = strlen (name) + 1;
  630.  
  631.   return (guchar *) name;
  632. }
  633.  
  634. static void
  635. gimp_dnd_set_brush_data (GtkWidget     *widget,
  636.              GtkSignalFunc  set_brush_func,
  637.              gpointer       set_brush_data,
  638.              guchar        *vals,
  639.              gint           format,
  640.              gint           length)
  641. {
  642.   GimpBrush *brush;
  643.   gchar *name;
  644.  
  645.   if ((format != 8) || (length < 1))
  646.     {
  647.       g_warning ("Received invalid brush data\n");
  648.       return;
  649.     }
  650.  
  651.   name = (gchar *) vals;
  652.  
  653.   if (strcmp (name, "Standard") == 0)
  654.     brush = brushes_get_standard_brush ();
  655.   else
  656.     brush = gimp_brush_list_get_brush (brush_list, name);
  657.  
  658.   if (brush)
  659.     (* (GimpDndDropBrushFunc) set_brush_func) (widget, brush, set_brush_data);
  660. }
  661.  
  662. void
  663. gimp_dnd_brush_source_set (GtkWidget            *widget,
  664.                GimpDndDragBrushFunc  get_brush_func,
  665.                gpointer              data)
  666. {
  667.   gimp_dnd_data_source_set (GIMP_DND_DATA_BRUSH, widget,
  668.                 GTK_SIGNAL_FUNC (get_brush_func),
  669.                 data);
  670. }
  671.  
  672. void
  673. gimp_dnd_brush_dest_set (GtkWidget            *widget,
  674.              GimpDndDropBrushFunc  set_brush_func,
  675.              gpointer              data)
  676. {
  677.   gimp_dnd_data_dest_set (GIMP_DND_DATA_BRUSH, widget,
  678.               GTK_SIGNAL_FUNC (set_brush_func),
  679.               data);
  680. }
  681.  
  682. /***************************/
  683. /*  pattern dnd functions  */
  684. /***************************/
  685.  
  686. static GtkWidget *
  687. gimp_dnd_get_pattern_icon (GtkWidget     *widget,
  688.                GtkSignalFunc  get_pattern_func,
  689.                gpointer       get_pattern_data)
  690. {
  691.   GtkWidget *preview;
  692.   GPattern  *pattern;
  693.  
  694.   pattern = (* (GimpDndDragPatternFunc) get_pattern_func) (widget,
  695.                                get_pattern_data);
  696.  
  697.   if (! pattern)
  698.     return NULL;
  699.  
  700.   preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  701.   gtk_preview_size (GTK_PREVIEW (preview), 
  702.                     DRAG_PREVIEW_SIZE, DRAG_PREVIEW_SIZE);      
  703.  
  704.   draw_pattern (GTK_PREVIEW (preview), pattern,
  705.         DRAG_PREVIEW_SIZE, DRAG_PREVIEW_SIZE);
  706.  
  707.   return preview;
  708. }
  709.  
  710. static guchar *
  711. gimp_dnd_get_pattern_data (GtkWidget     *widget,
  712.                GtkSignalFunc  get_pattern_func,
  713.                gpointer       get_pattern_data,
  714.                gint          *format,
  715.                gint          *length)
  716. {
  717.   GPattern *pattern;
  718.   gchar *name;
  719.  
  720.   pattern = (* (GimpDndDragPatternFunc) get_pattern_func) (widget,
  721.                                get_pattern_data);
  722.  
  723.   if (! pattern)
  724.     return NULL;
  725.  
  726.   name = g_strdup (pattern->name);
  727.  
  728.   *format = 8;
  729.   *length = strlen (name) + 1;
  730.  
  731.   return (guchar *) name;
  732. }
  733.  
  734. static void
  735. gimp_dnd_set_pattern_data (GtkWidget     *widget,
  736.                GtkSignalFunc  set_pattern_func,
  737.                gpointer       set_pattern_data,
  738.                guchar        *vals,
  739.                gint           format,
  740.                gint           length)
  741. {
  742.   GPattern *pattern;
  743.   gchar *name;
  744.  
  745.   if ((format != 8) || (length < 1))
  746.     {
  747.       g_warning ("Received invalid pattern data\n");
  748.       return;
  749.     }
  750.  
  751.   name = (gchar *) vals;
  752.  
  753.   if (strcmp (name, "Standard") == 0)
  754.     pattern = patterns_get_standard_pattern ();
  755.   else
  756.     pattern = pattern_list_get_pattern (pattern_list, name);
  757.  
  758.   if (pattern)
  759.     (* (GimpDndDropPatternFunc) set_pattern_func) (widget, pattern,
  760.                            set_pattern_data);
  761. }
  762.  
  763. void
  764. gimp_dnd_pattern_source_set (GtkWidget              *widget,
  765.                  GimpDndDragPatternFunc  get_pattern_func,
  766.                  gpointer                data)
  767. {
  768.   gimp_dnd_data_source_set (GIMP_DND_DATA_PATTERN, widget,
  769.                 GTK_SIGNAL_FUNC (get_pattern_func),
  770.                 data);
  771. }
  772.  
  773. void
  774. gimp_dnd_pattern_dest_set (GtkWidget              *widget,
  775.                GimpDndDropPatternFunc  set_pattern_func,
  776.                gpointer                data)
  777. {
  778.   gimp_dnd_data_dest_set (GIMP_DND_DATA_PATTERN, widget,
  779.               GTK_SIGNAL_FUNC (set_pattern_func),
  780.               data);
  781. }
  782.  
  783. /****************************/
  784. /*  gradient dnd functions  */
  785. /****************************/
  786.  
  787. static GtkWidget *
  788. gimp_dnd_get_gradient_icon (GtkWidget     *widget,
  789.                 GtkSignalFunc  get_gradient_func,
  790.                 gpointer       get_gradient_data)
  791. {
  792.   GtkWidget  *preview;
  793.   gradient_t *gradient;
  794.  
  795.   gradient =
  796.     (* (GimpDndDragGradientFunc) get_gradient_func) (widget, get_gradient_data);
  797.  
  798.   if (! gradient)
  799.     return NULL;
  800.  
  801.   preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  802.   gtk_preview_size (GTK_PREVIEW (preview), 
  803.                     DRAG_PREVIEW_SIZE * 2, DRAG_PREVIEW_SIZE / 2);      
  804.  
  805.   draw_gradient (GTK_PREVIEW (preview), gradient,
  806.          DRAG_PREVIEW_SIZE * 2, DRAG_PREVIEW_SIZE / 2);
  807.  
  808.   return preview;
  809. }
  810.  
  811. static guchar *
  812. gimp_dnd_get_gradient_data (GtkWidget     *widget,
  813.                 GtkSignalFunc  get_gradient_func,
  814.                 gpointer       get_gradient_data,
  815.                 gint          *format,
  816.                 gint          *length)
  817. {
  818.   gradient_t *gradient;
  819.   gchar *name;
  820.  
  821.   gradient =
  822.     (* (GimpDndDragGradientFunc) get_gradient_func) (widget, get_gradient_data);
  823.  
  824.   if (! gradient)
  825.     return NULL;
  826.  
  827.   name = g_strdup (gradient->name);
  828.  
  829.   *format = 8;
  830.   *length = strlen (name) + 1;
  831.  
  832.   return (guchar *) name;
  833. }
  834.  
  835. static void
  836. gimp_dnd_set_gradient_data (GtkWidget     *widget,
  837.                 GtkSignalFunc  set_gradient_func,
  838.                 gpointer       set_gradient_data,
  839.                 guchar        *vals,
  840.                 gint           format,
  841.                 gint           length)
  842. {
  843.   gradient_t *gradient;
  844.   gchar *name;
  845.  
  846.   if ((format != 8) || (length < 1))
  847.     {
  848.       g_warning ("Received invalid gradient data\n");
  849.       return;
  850.     }
  851.  
  852.   name = (gchar *) vals;
  853.  
  854.   if (strcmp (name, "Standard") == 0)
  855.     gradient = gradients_get_standard_gradient ();
  856.   else
  857.     gradient = gradient_list_get_gradient (gradients_list, name);
  858.  
  859.   if (gradient)
  860.     (* (GimpDndDropGradientFunc) set_gradient_func) (widget, gradient,
  861.                              set_gradient_data);
  862. }
  863.  
  864. void
  865. gimp_dnd_gradient_source_set (GtkWidget               *widget,
  866.                   GimpDndDragGradientFunc  get_gradient_func,
  867.                   gpointer                 data)
  868. {
  869.   gimp_dnd_data_source_set (GIMP_DND_DATA_GRADIENT, widget,
  870.                 GTK_SIGNAL_FUNC (get_gradient_func),
  871.                 data);
  872. }
  873.  
  874. void
  875. gimp_dnd_gradient_dest_set (GtkWidget               *widget,
  876.                 GimpDndDropGradientFunc  set_gradient_func,
  877.                 gpointer                 data)
  878. {
  879.   gimp_dnd_data_dest_set (GIMP_DND_DATA_GRADIENT, widget,
  880.               GTK_SIGNAL_FUNC (set_gradient_func),
  881.               data);
  882. }
  883.  
  884. /***************************/
  885. /*  palette dnd functions  */
  886. /***************************/
  887.  
  888. static GtkWidget *
  889. gimp_dnd_get_palette_icon (GtkWidget     *widget,
  890.                GtkSignalFunc  get_gradient_func,
  891.                gpointer       get_gradient_data)
  892. {
  893.   return NULL;
  894. }
  895.  
  896. static guchar *
  897. gimp_dnd_get_palette_data (GtkWidget     *widget,
  898.                GtkSignalFunc  get_gradient_func,
  899.                gpointer       get_gradient_data,
  900.                gint          *format,
  901.                gint          *length)
  902. {
  903.   return NULL;
  904. }
  905.  
  906. static void
  907. gimp_dnd_set_palette_data (GtkWidget     *widget,
  908.                GtkSignalFunc  set_gradient_func,
  909.                gpointer       set_gradient_data,
  910.                guchar        *vals,
  911.                gint           format,
  912.                gint           length)
  913. {
  914. }
  915.  
  916. void
  917. gimp_dnd_palette_source_set (GtkWidget              *widget,
  918.                  GimpDndDragPaletteFunc  get_palette_func,
  919.                  gpointer                data)
  920. {
  921.   gimp_dnd_data_source_set (GIMP_DND_DATA_PALETTE, widget,
  922.                 GTK_SIGNAL_FUNC (get_palette_func),
  923.                 data);
  924. }
  925.  
  926. void
  927. gimp_dnd_palette_dest_set (GtkWidget              *widget,
  928.                GimpDndDropPaletteFunc  set_palette_func,
  929.                gpointer                data)
  930. {
  931.   gimp_dnd_data_dest_set (GIMP_DND_DATA_PALETTE, widget,
  932.               GTK_SIGNAL_FUNC (set_palette_func),
  933.               data);
  934. }
  935.  
  936. /************************/
  937. /*  tool dnd functions  */
  938. /************************/
  939.  
  940. static GtkWidget *
  941. gimp_dnd_get_tool_icon (GtkWidget     *widget,
  942.             GtkSignalFunc  get_tool_func,
  943.             gpointer       get_tool_data)
  944. {
  945.   GtkWidget *tool_icon;
  946.   ToolType   tool_type;
  947.  
  948.   tool_type =
  949.     (* (GimpDndDragToolFunc) get_tool_func) (widget, get_tool_data);
  950.  
  951.   if (((gint) tool_type < 0) || ((gint) tool_type >= num_tools))
  952.     return NULL;
  953.  
  954.   tool_icon = gtk_pixmap_new (tool_get_pixmap (tool_type),
  955.                   tool_get_mask (tool_type));
  956.  
  957.   return tool_icon;
  958. }
  959.  
  960. static guchar *
  961. gimp_dnd_get_tool_data (GtkWidget     *widget,
  962.             GtkSignalFunc  get_tool_func,
  963.             gpointer       get_tool_data,
  964.             gint          *format,
  965.             gint          *length)
  966. {
  967.   ToolType  tool_type;
  968.   guint16  *val;
  969.  
  970.   tool_type =
  971.     (* (GimpDndDragToolFunc) get_tool_func) (widget, get_tool_data);
  972.  
  973.   if (((gint) tool_type < 0) || ((gint) tool_type >= num_tools))
  974.     return NULL;
  975.  
  976.   val = g_new (guint16, 1);
  977.  
  978.   val[0] = (guint16) tool_type;
  979.  
  980.   *format = 16;
  981.   *length = 2;
  982.  
  983.   return (guchar *) val;
  984. }
  985.  
  986. static void
  987. gimp_dnd_set_tool_data (GtkWidget     *widget,
  988.             GtkSignalFunc  set_tool_func,
  989.             gpointer       set_tool_data,
  990.             guchar        *vals,
  991.             gint           format,
  992.             gint           length)
  993. {
  994.   ToolType tool_type;
  995.   guint16 val;
  996.  
  997.   if ((format != 16) || (length != 2))
  998.     {
  999.       g_warning ("Received invalid tool data\n");
  1000.       return;
  1001.     }
  1002.  
  1003.   val = *((guint16 *) vals);
  1004.  
  1005.   tool_type = (ToolType) val;
  1006.  
  1007.   if (((gint) tool_type < 0) || ((gint) tool_type >= num_tools))
  1008.     return;
  1009.  
  1010.   (* (GimpDndDropToolFunc) set_tool_func) (widget, tool_type, set_tool_data);
  1011. }
  1012.  
  1013. void
  1014. gimp_dnd_tool_source_set (GtkWidget           *widget,
  1015.               GimpDndDragToolFunc  get_tool_func,
  1016.               gpointer             data)
  1017. {
  1018.   gimp_dnd_data_source_set (GIMP_DND_DATA_TOOL, widget,
  1019.                 GTK_SIGNAL_FUNC (get_tool_func),
  1020.                 data);
  1021. }
  1022.  
  1023. void
  1024. gimp_dnd_tool_dest_set (GtkWidget           *widget,
  1025.             GimpDndDropToolFunc  set_tool_func,
  1026.             gpointer             data)
  1027. {
  1028.   gimp_dnd_data_dest_set (GIMP_DND_DATA_TOOL, widget,
  1029.               GTK_SIGNAL_FUNC (set_tool_func),
  1030.               data);
  1031. }
  1032.  
  1033. /****************************/
  1034. /*  drawable dnd functions  */
  1035. /****************************/
  1036.  
  1037. void
  1038. gimp_dnd_set_drawable_preview_icon (GtkWidget      *widget,
  1039.                     GdkDragContext *context,
  1040.                     GimpDrawable   *drawable)
  1041. {
  1042.   GtkWidget *window;
  1043.   GtkWidget *frame;
  1044.   GtkWidget *preview;
  1045.  
  1046.   gboolean  drag_connected;
  1047.  
  1048.   TempBuf   *tmpbuf;
  1049.   gint       bpp;
  1050.   gint       x, y;
  1051.   guchar    *src;
  1052.   gdouble    r, g, b, a;
  1053.   gdouble    c0, c1;
  1054.   guchar    *p0, *p1, *even, *odd;
  1055.   gint       width;
  1056.   gint       height;
  1057.   gdouble    ratio;
  1058.  
  1059.   if (! preview_size)
  1060.     return;
  1061.  
  1062.   if (gimp_drawable_width (drawable) > gimp_drawable_height (drawable))
  1063.     ratio = (gdouble) DRAG_PREVIEW_SIZE / 
  1064.             (gdouble) (gimp_drawable_width (drawable));
  1065.   else
  1066.     ratio = (gdouble) DRAG_PREVIEW_SIZE /
  1067.             (gdouble) (gimp_drawable_height (drawable));
  1068.  
  1069.   width =  (gint) (ratio * gimp_drawable_width (drawable));
  1070.   height = (gint) (ratio * gimp_drawable_height (drawable));
  1071.  
  1072.   if (width < 1) 
  1073.     width = 1;
  1074.   if (height < 1)
  1075.     height = 1;
  1076.  
  1077.   preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  1078.   gtk_preview_size (GTK_PREVIEW (preview), width, height);
  1079.  
  1080.   if (GIMP_IS_LAYER (drawable))
  1081.     {
  1082.       tmpbuf = layer_preview (GIMP_LAYER (drawable), width, height);
  1083.     }
  1084.   else if (GIMP_IS_LAYER_MASK (drawable))
  1085.     {
  1086.       tmpbuf =
  1087.     layer_mask_preview (layer_mask_get_layer (GIMP_LAYER_MASK (drawable)),
  1088.                 width, height);
  1089.     }
  1090.   else if (GIMP_IS_CHANNEL (drawable))
  1091.     {
  1092.       tmpbuf = channel_preview (GIMP_CHANNEL (drawable), width, height);
  1093.     }
  1094.   else
  1095.     {
  1096.       gtk_widget_destroy (preview);
  1097.       return;
  1098.     }
  1099.  
  1100.   bpp = tmpbuf->bytes;
  1101.  
  1102.   /*  Draw the thumbnail with checks  */
  1103.   src = temp_buf_data (tmpbuf);
  1104.  
  1105.   even = g_new (guchar, width * 3);
  1106.   odd  = g_new (guchar, width * 3);
  1107.   
  1108.   for (y = 0; y < height; y++)
  1109.     {
  1110.       p0 = even;
  1111.       p1 = odd;
  1112.  
  1113.       for (x = 0; x < width; x++)
  1114.     {
  1115.       if (bpp == 4)
  1116.         {
  1117.           r = ((gdouble) src[x*4+0]) / 255.0;
  1118.           g = ((gdouble) src[x*4+1]) / 255.0;
  1119.           b = ((gdouble) src[x*4+2]) / 255.0;
  1120.           a = ((gdouble) src[x*4+3]) / 255.0;
  1121.         }
  1122.       else if (bpp == 3)
  1123.         {
  1124.           r = ((gdouble) src[x*3+0]) / 255.0;
  1125.           g = ((gdouble) src[x*3+1]) / 255.0;
  1126.           b = ((gdouble) src[x*3+2]) / 255.0;
  1127.           a = 1.0;
  1128.         }
  1129.       else
  1130.         {
  1131.           r = ((gdouble) src[x*bpp+0]) / 255.0;
  1132.           g = b = r;
  1133.           if (bpp == 2)
  1134.         a = ((gdouble) src[x*bpp+1]) / 255.0;
  1135.           else
  1136.         a = 1.0;
  1137.         }
  1138.  
  1139.       if ((x / GIMP_CHECK_SIZE_SM) & 1)
  1140.         {
  1141.           c0 = GIMP_CHECK_LIGHT;
  1142.           c1 = GIMP_CHECK_DARK;
  1143.         }
  1144.       else
  1145.         {
  1146.           c0 = GIMP_CHECK_DARK;
  1147.           c1 = GIMP_CHECK_LIGHT;
  1148.         }
  1149.  
  1150.       *p0++ = (c0 + (r - c0) * a) * 255.0;
  1151.       *p0++ = (c0 + (g - c0) * a) * 255.0;
  1152.       *p0++ = (c0 + (b - c0) * a) * 255.0;
  1153.  
  1154.       *p1++ = (c1 + (r - c1) * a) * 255.0;
  1155.       *p1++ = (c1 + (g - c1) * a) * 255.0;
  1156.       *p1++ = (c1 + (b - c1) * a) * 255.0;
  1157.  
  1158.     }
  1159.  
  1160.       if ((y / GIMP_CHECK_SIZE_SM) & 1)
  1161.     {
  1162.       gtk_preview_draw_row (GTK_PREVIEW (preview), odd,
  1163.                 0, y, width);
  1164.     }
  1165.       else
  1166.     {
  1167.       gtk_preview_draw_row (GTK_PREVIEW (preview), even,
  1168.                 0, y, width);
  1169.     }
  1170.       src += width * bpp;
  1171.     }
  1172.  
  1173.   g_free (even);
  1174.   g_free (odd);
  1175.  
  1176.   window = gtk_window_new (GTK_WINDOW_POPUP);
  1177.   gtk_widget_realize (window);
  1178.  
  1179.   frame = gtk_frame_new (NULL);
  1180.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
  1181.   gtk_container_add (GTK_CONTAINER (window), frame);
  1182.   gtk_widget_show (frame);
  1183.  
  1184.   gtk_container_add (GTK_CONTAINER (frame), preview);
  1185.   gtk_widget_show (preview);
  1186.  
  1187.   drag_connected =
  1188.     (gboolean) gtk_object_get_data (GTK_OBJECT (widget),
  1189.                     "gimp_dnd_drag_connected");
  1190.  
  1191.   if (! drag_connected)
  1192.     {
  1193.       gtk_signal_connect (GTK_OBJECT (widget), "drag_end",
  1194.               GTK_SIGNAL_FUNC (gimp_dnd_data_drag_end),
  1195.               NULL);
  1196.  
  1197.       gtk_object_set_data (GTK_OBJECT (widget), "gimp_dnd_drag_connected",
  1198.                (gpointer) TRUE);
  1199.     }
  1200.  
  1201.   gtk_object_set_data_full (GTK_OBJECT (widget),
  1202.                 "gimp-dnd-data-widget",
  1203.                 window,
  1204.                 (GtkDestroyNotify) gtk_widget_destroy);
  1205.  
  1206.   gtk_drag_set_icon_widget (context, window,
  1207.                 DRAG_ICON_OFFSET, DRAG_ICON_OFFSET);
  1208. }
  1209.  
  1210. /******************************/
  1211. /*  file / url dnd functions  */
  1212. /******************************/
  1213.  
  1214. static void
  1215. gimp_dnd_file_open_files (gchar *buffer)
  1216. {
  1217.   gchar  name_buffer[1024];
  1218.   const gchar *data_type = "file:";
  1219.   const gint   sig_len = strlen (data_type);
  1220.  
  1221.   while (*buffer)
  1222.     {
  1223.       gchar *name = name_buffer;
  1224.       gint len = 0;
  1225.  
  1226.       while ((*buffer != 0) && (*buffer != '\n') && len < 1024)
  1227.         {
  1228.           *name++ = *buffer++;
  1229.           len++;
  1230.         }
  1231.       if (len == 0)
  1232.         break;
  1233.  
  1234.       if (*(name - 1) == 0xd)   /* gmc uses RETURN+NEWLINE as delimiter */
  1235.         *(name - 1) = '\0';
  1236.       else
  1237.         *name = '\0';
  1238.       name = name_buffer;
  1239.       if ((sig_len < len) && (! strncmp (name, data_type, sig_len)))
  1240.         name += sig_len;
  1241.  
  1242.       if (name && strlen (name) > 2)
  1243.     file_open (name, name);
  1244.  
  1245.       if (*buffer)
  1246.         buffer++;
  1247.     }
  1248. }
  1249.  
  1250. static void
  1251. gimp_dnd_file_drag_data_received (GtkWidget        *widget,
  1252.                   GdkDragContext   *context,
  1253.                   gint              x,
  1254.                   gint              y,
  1255.                   GtkSelectionData *data,
  1256.                   guint             info,
  1257.                   guint             time)
  1258. {
  1259.   switch (context->action)
  1260.     {
  1261.     case GDK_ACTION_DEFAULT:
  1262.     case GDK_ACTION_COPY:
  1263.     case GDK_ACTION_MOVE:
  1264.     case GDK_ACTION_LINK:
  1265.     case GDK_ACTION_ASK:
  1266.     default:
  1267.       gimp_dnd_file_open_files ((gchar *) data->data);
  1268.       gtk_drag_finish (context, TRUE, FALSE, time);
  1269.       break;
  1270.     }
  1271.   return;
  1272. }
  1273.  
  1274. void
  1275. gimp_dnd_file_dest_set (GtkWidget *widget)
  1276. {
  1277.   gtk_signal_connect (GTK_OBJECT (widget), "drag_data_received",
  1278.                       GTK_SIGNAL_FUNC (gimp_dnd_file_drag_data_received),
  1279.                       widget);
  1280. }
  1281.  
  1282.