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