1 /*
2  * dnd.c - all of the stuff for the drag-and-drop interaction that gwave does.
3  *
4  * Copyright (C) 1998, 1999 Stephen G. Tell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  *
21  * This used to include compatibility code for Gtk+ 1.0 and 1.2.
22  */
23 
24 #include <ctype.h>
25 #include <math.h>
26 #include <setjmp.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <sys/time.h>
34 #include <gtk/gtk.h>
35 
36 #include <config.h>
37 #include <gwave.h>
38 #include <wavelist.h>
39 
40 #include "gtkmisc.h"
41 
42 
43 #define GWAVE_PRIVATE_DND_MAGIC	0xf00bbaad
44 
45 enum {
46   TARGET_STRING = 0,
47   TARGET_DVAR = 1,
48   TARGET_ROOTWIN = 2,
49   TARGET_URL = 3
50 };
51 
52 static GtkTargetEntry target_table[] = {
53   { "x-gwave/dvar", GTK_TARGET_SAME_APP, TARGET_DVAR },
54   { "STRING",     0, TARGET_STRING },
55   { "text/plain", 0, TARGET_STRING },
56   { "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
57 };
58 static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
59 
60 static GdkPixmap *drag_icon_pixmap;
61 static GdkPixmap *drag_mask_pixmap;
62 
63 /*
64  * set up for drag & drop.
65  */
66 void
dnd_init(GtkWidget * window)67 dnd_init(GtkWidget *window)
68 {
69 	static GtkWidget *drag_icon = NULL;
70 	static GtkWidget *drop_icon = NULL;
71 
72 	if(!drag_icon_pixmap)
73 		drag_icon_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
74 			  gtk_widget_get_colormap(GTK_WIDGET(window)),
75 			  &drag_mask_pixmap,
76 		          NULL, wave_drag_ok_xpm);
77 }
78 
79 /****************************************************************************
80  *
81  * event handler for a drop onto the target, in our case
82  * when variable gets dropped on a wavepanel
83  */
84 
85 void
dnd_target_event(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * data,guint info,guint time,gpointer d)86 dnd_target_event(GtkWidget          *widget,
87 		 GdkDragContext     *context,
88 		 gint                x,
89 		 gint                y,
90 		 GtkSelectionData   *data,
91 		 guint               info,
92 		 guint               time,
93 		 gpointer d)
94 {
95 	WavePanel *wp = (WavePanel *)d;
96 
97 	GWDnDData dd;
98 /*	g_print("dnd_target_event info=%d length=%d\n", info, data->length); */
99 
100 	switch(info) {
101 	case TARGET_DVAR:
102 		dd = *(GWDnDData *)data->data;
103 		if(data->length == sizeof(GWDnDData)
104 		 && dd.magic == GWAVE_PRIVATE_DND_MAGIC) {
105 /*			g_print("dnd_target_event recieved dv=0x%lx\n", dd.dv); */
106 			add_var_to_panel(wp, dd.dv);
107 		} else {
108 			g_print("dnd_target_event bad magic number %lx\n",
109 				dd.magic);
110 		}
111 		gtk_drag_finish (context, TRUE, FALSE, time);
112 		break;
113 	case TARGET_STRING:
114 		/* eventually we may be able to do somthing useful with
115 		 * a dropped string or other drop data types.
116 		 * For example dropping between multiple
117 		 * running gwaves, or dropping between a simulator
118 		 * and gwave.
119 		 */
120 		g_print("dnd_target_event: received \"%s\"\n",
121 			(gchar *)data->data);
122 		gtk_drag_finish (context, TRUE, FALSE, time);
123 	default:
124 		gtk_drag_finish (context, FALSE, FALSE, time);
125 	}
126 }
127 
128 
129 /*
130  * Set up a widget as a drop target
131  */
132 void
dnd_setup_target(GtkWidget * w,gpointer * d)133 dnd_setup_target(GtkWidget *w, gpointer *d)
134 {
135 	gtk_drag_dest_set (w,
136 			   GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION,
137 			   target_table, n_targets - 1,/*no rootwin*/
138 			   GDK_ACTION_COPY | GDK_ACTION_MOVE);
139 
140 	gtk_signal_connect (GTK_OBJECT (w),
141 			    "drag_data_received",
142 			    GTK_SIGNAL_FUNC(dnd_target_event), d);
143 }
144 
145 
146 /*****************************************************************************
147  *
148  * Prepare drag-and-drop data at the source, so the
149  * underlying stuff can magicly transfer it to the target.
150  */
151 
152 void
dnd_source_data_get(GtkWidget * widget,GdkDragContext * context,GtkSelectionData * selection_data,guint info,guint time,gpointer d)153 dnd_source_data_get(GtkWidget          *widget,
154 		       GdkDragContext     *context,
155 		       GtkSelectionData   *selection_data,
156 		       guint               info,
157 		       guint               time,
158 		    gpointer d)
159 {
160 	WaveVar *dv = (WaveVar *)d;
161 	GWDnDData dd;
162 	GWDataFile *gdf;
163 	char buf[1024];
164 
165 /*	g_print("dnd_source_data_get: type=%d\n", info); */
166 
167 	switch(info) {
168 	case TARGET_ROOTWIN:
169 		/* maybe this could eventually mean somthing? */
170 /* 		g_print("wavevar %s dropped on the rootwin\n",
171 		   dv->wv_name);*/
172 		break;
173 	case TARGET_STRING:
174 		gdf = wvar_gwdatafile(dv);
175 		sprintf(buf, "%s;%s",
176 			gdf->wf->wf_filename,
177 			dv->wv_name);
178 
179 		gtk_selection_data_set (selection_data,
180 					selection_data->target,
181 					8, buf, strlen(buf));
182 		break;
183 	case TARGET_DVAR:
184 		dd.magic = GWAVE_PRIVATE_DND_MAGIC;
185 		dd.dv = dv;
186 /*		g_print("source_data_get: dv=%lx\n", dv); */
187 		gtk_selection_data_set (selection_data,
188 					selection_data->target,
189 					8, (gpointer)&dd, sizeof(GWDnDData));
190 		break;
191 	default:
192 		g_print("unknown target type\n");
193 	}
194 }
195 
196 
197 void
dnd_source_data_delete(GtkWidget * widget,GdkDragContext * context,gpointer data)198 dnd_source_data_delete(GtkWidget          *widget,
199 			  GdkDragContext     *context,
200 			  gpointer            data)
201 {
202 	g_print("dnd_source_data_delete() called\n");
203 }
204 
205 
206 /*
207  * Set up a widget as a drag source
208  */
209 void
dnd_setup_source(GtkWindow * window,GtkWidget * w,WaveVar * dv)210 dnd_setup_source(GtkWindow *window, GtkWidget *w, WaveVar *dv)
211 {
212 
213 	gtk_drag_source_set (w, GDK_BUTTON1_MASK,
214 			     target_table, n_targets,
215 			     GDK_ACTION_COPY | GDK_ACTION_MOVE);
216 	gtk_drag_source_set_icon (w,
217 				  gtk_widget_get_colormap(GTK_WIDGET(window)),
218 				  drag_icon_pixmap, drag_mask_pixmap);
219 
220 	gtk_signal_connect (GTK_OBJECT(w), "drag_data_get",
221 			    GTK_SIGNAL_FUNC(dnd_source_data_get),
222 			    (gpointer) dv);
223 
224 	gtk_signal_connect (GTK_OBJECT(w), "drag_data_delete",
225 			    GTK_SIGNAL_FUNC (dnd_source_data_delete), NULL);
226 
227 }
228 
229