1 /*
2  * ===========================
3  * VDK Visual Development Kit
4  * Version 1.0.3
5  * November 1999
6  * ===========================
7  *
8  * Copyright (C) 1998, Mario Motta
9  * Developed by Mario Motta <mmotta@guest.net>
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23  * 02111-1307, USA.
24  */
25 
26 #include <vdk/vdkdnd.h>
27 
28 
VDKDnDEntry(VDKObject * object,VDKDnD * dnd,GtkWidget * widget)29 VDKDnDEntry::VDKDnDEntry(VDKObject* object, VDKDnD* dnd, GtkWidget* widget):
30     object(object),dnd(dnd),widget(widget)
31 {
32 }
33 
34 /*
35 */
VDKDnD(VDKForm * owner,GtkTargetEntry * target_table,guint n_entries)36 VDKDnD::VDKDnD(VDKForm* owner,
37             GtkTargetEntry* target_table,
38             guint n_entries):
39             VDKRawObject(owner),
40             target_table(target_table),
41             n_entries(n_entries),
42             DragSource("DragSource",this,NULL),
43 	    DragPoint("DragPoint",this,VDKPoint(-1,-1))
44 {
45 }
46 
47 /*
48 */
~VDKDnD()49 VDKDnD::~VDKDnD()
50 {
51 // free sources and targets tables entries
52 VDKDnDIterator ls(sources);
53 for(;ls;ls++)
54     delete ls.current();
55 VDKDnDIterator lt(targets);
56 for(;lt;lt++)
57     delete lt.current();
58 }
59 /*
60 */
61 void
AddSource(VDKObject * source)62 VDKDnD::AddSource(VDKObject* source)
63 {
64 // sets source
65 GtkWidget* src_widget = NULL;
66 if(!src_widget)
67     {
68     VDKCustom* custom = dynamic_cast<VDKCustom*>(source);
69     src_widget = custom ? custom->CustomWidget() : NULL;
70     }
71 /*
72 if(!src_widget)
73     {
74     VDKCustom* checkbutton = dynamic_cast<VDKCustom*>(source);
75     src_widget = checkbutton ? GTK_BIN(checkbutton->Widget())->child : NULL;
76     }
77 */
78 if(!src_widget)
79     src_widget = source->Widget();
80 
81 gtk_drag_source_set(
82                    src_widget,
83                    (GdkModifierType)(GDK_BUTTON1_MASK | GDK_BUTTON3_MASK),
84 		   target_table, n_entries,
85 		   GdkDragAction(GDK_ACTION_COPY |GDK_ACTION_MOVE)
86                    );
87 
88 VDKDnDEntry *entry = new VDKDnDEntry(source,this,src_widget);
89 sources.add(entry);
90 gtk_signal_connect (GTK_OBJECT (src_widget), "drag_data_get",
91   		    GTK_SIGNAL_FUNC (VDKDnD::source_drag_data_get),
92                     entry);
93 
94 }
95 /*
96 */
97 void
AddTarget(VDKObject * target)98 VDKDnD::AddTarget(VDKObject* target)
99 {
100 GtkWidget* src_widget = NULL;
101 src_widget = target->WrappedWidget();
102 // sets target
103 gtk_drag_dest_set (src_widget,
104                     GTK_DEST_DEFAULT_ALL,
105    		    target_table, n_entries,
106                     GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE) );
107 VDKDnDEntry *entry = new VDKDnDEntry(target,this,src_widget);
108 targets.add(entry);
109 // connect target to drop signal
110 gtk_signal_connect (GTK_OBJECT (src_widget), "drag_drop",
111 		      GTK_SIGNAL_FUNC (VDKDnD::drag_drop), entry);
112 gtk_signal_connect (GTK_OBJECT (src_widget), "drag_leave",
113 		      GTK_SIGNAL_FUNC (VDKDnD::drag_leave), entry);
114 gtk_signal_connect (GTK_OBJECT (src_widget), "drag_motion",
115 		      GTK_SIGNAL_FUNC (VDKDnD::drag_motion), entry);
116 }
117 
118 /*
119 */
120 gboolean
drag_drop(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time,gpointer data)121 VDKDnD::drag_drop(GtkWidget	*widget,
122                GdkDragContext *context,
123                gint x,
124                gint y,
125                guint time,
126                gpointer data)
127 {
128   g_return_val_if_fail(widget != NULL, FALSE);
129   g_return_val_if_fail(data != NULL, FALSE);
130   VDKDnDEntry* targetdata = reinterpret_cast<VDKDnDEntry*>(data);
131   if (context && context->targets)
132     {
133     targetdata->dnd->DragPoint(VDKPoint(x,y));
134     targetdata->object->SignalEmit(dnd_dropped_signal);
135     targetdata->object->SignalEmit("dnd_dropped");
136     return TRUE;
137     }
138   return FALSE;
139 }
140 
141 /*
142 */
143 void
source_drag_data_get(GtkWidget * widget,GdkDragContext * context,GtkSelectionData * selection_data,guint info,guint time,gpointer data)144 VDKDnD::source_drag_data_get(GtkWidget *widget,
145                              GdkDragContext     *context,
146                            	 GtkSelectionData   *selection_data,
147                              guint               info,
148                              guint               time,
149                              gpointer            data)
150 {
151     g_return_if_fail(widget != NULL);
152     g_return_if_fail(data != NULL);
153     VDKDnDEntry* sourcedata = reinterpret_cast<VDKDnDEntry*>(data);
154     if (context && context->targets)
155         {
156         sourcedata->object->SignalEmit(dnd_get_data_signal);
157         sourcedata->object->SignalEmit("dnd_get_data");
158         gtk_drag_finish (context, FALSE, FALSE, time);
159         sourcedata->dnd->DragSource(sourcedata->object);
160         }
161 }
162 /*
163 */
164 gboolean
drag_motion(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time,gpointer data)165 VDKDnD::drag_motion	   (GtkWidget	       *widget,
166 			    GdkDragContext     *context,
167 			    gint                x,
168 			    gint                y,
169 			    guint               time,
170                         gpointer data)
171 {
172     g_return_val_if_fail(widget != NULL,FALSE);
173     g_return_val_if_fail(data != NULL, FALSE);
174     g_return_val_if_fail(context != NULL, FALSE);
175     VDKDnDEntry* targetdata = reinterpret_cast<VDKDnDEntry*>(data);
176     GtkWidget *source_widget;
177     source_widget = gtk_drag_get_source_widget (context);
178     // look on the source table to find source object
179     targetdata->dnd->DragSource(NULL);
180     VDKDnDIterator li(targetdata->dnd->sources);
181     for(;li;li++)
182         {
183         if(li.current()->widget == source_widget)
184 	    {
185             targetdata->dnd->DragSource(li.current()->object);
186 	    targetdata->dnd->DragPoint(VDKPoint(x,y));
187 	    }
188 	}
189     targetdata->object->SignalEmit(dnd_drag_motion_signal);
190     targetdata->object->SignalEmit("dnd_drag_motion");
191     return TRUE;
192 }
193 
194 void
drag_leave(GtkWidget * widget,GdkDragContext * context,guint time,gpointer data)195 VDKDnD::drag_leave  (GtkWidget	*widget,
196                             GdkDragContext  *context,
197                             guint  time,
198                             gpointer data)
199 {
200   g_return_if_fail(widget != NULL);
201   g_return_if_fail(data != NULL);
202   VDKDnDEntry* targetdata = reinterpret_cast<VDKDnDEntry*>(data);
203   if (context && context->targets)
204     {
205     targetdata->object->SignalEmit(dnd_drag_leave_signal);
206     targetdata->object->SignalEmit("dnd_drag_leave");
207     }
208 }
209 
210 /*
211  */
212 void
SetIcon(VDKObject * widget,VDKRawPixmap * pixmap)213 VDKDnD::SetIcon(VDKObject* widget, VDKRawPixmap* pixmap)
214 {
215   VDKDnDIterator li(sources);
216   for(;li;li++)
217     {
218       if(li.current()->object == widget)
219 	{
220 	  gtk_drag_source_set_icon (li.current()->widget,
221 			  gtk_widget_get_colormap(li.current()->widget),
222 			  *pixmap, pixmap->Mask());
223 	  break;
224 	}
225     }
226 }
227 
228 /*
229  */
230 void
RemoveSource(VDKObject * source)231 VDKDnD::RemoveSource(VDKObject* source)
232 {
233   int t = 0;
234   VDKDnDIterator li(sources);
235   for(;li;li++,t++)
236     {
237       if(li.current()->object == source)
238 	{
239 	  gtk_drag_source_unset(li.current()->widget);
240 	  break;
241 	}
242     }
243   if(t < sources.size())
244     sources.remove(sources[t]);
245 }
246 
247 /*
248  */
249 void
RemoveTarget(VDKObject * target)250 VDKDnD::RemoveTarget(VDKObject* target)
251 {
252   int t = 0;
253   VDKDnDIterator li(targets);
254   for(;li;li++,t++)
255     {
256       if(li.current()->object == target)
257 	{
258 	  gtk_drag_dest_unset(li.current()->widget);
259 	  break;
260 	}
261     }
262   if(t < targets.size())
263     targets.remove(targets[t]);
264 }
265