1 /* $TOG: dragsource.c /main/6 1997/03/05 11:46:31 dbl $ */
2 /*
3 * Motif
4 *
5 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
6 *
7 * These libraries and programs are free software; you can
8 * redistribute them and/or modify them under the terms of the GNU
9 * Lesser General Public License as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * These libraries and programs are distributed in the hope that
14 * they will be useful, but WITHOUT ANY WARRANTY; without even the
15 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU Lesser General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with these librararies and programs; if not, write
21 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
22 * Floor, Boston, MA 02110-1301 USA
23 */
24 /*
25 * HISTORY
26 */
27
28 /*
29 * The Airport Drag And Drop Demo
30 *
31 * The module that contains all drag source / initiator code
32 *
33 * Created: Vania JOLOBOFF / May 1992
34 *
35 */
36
37 #include <Xm/XmAll.h>
38 #include "airport.h"
39 #include "dragsource.h"
40
41 /* ============================ prototypes ======================= */
42
43 static void EnterTopLevel(Widget dc, Airport this,
44 XmTopLevelEnterCallbackStruct *call_data);
45 /* drag callback entering top level window */
46
47 static void LeaveTopLevel(Widget dc, Airport this,
48 XmTopLevelLeaveCallbackStruct *call_data);
49 /* drag callback leaving top level window */
50
51 static void DropSiteEnter(Widget dc, Airport this,
52 XmDropSiteEnterCallbackStruct *call_data);
53 /* drag callback entering drop site */
54
55 static void DropSiteLeave(Widget dc, Airport this,
56 XmDropSiteLeaveCallbackStruct *call_data);
57 /* drag callback leaving drop site */
58
59 static void Flying(Widget dc, Airport this,
60 XmDragMotionCallbackStruct *call_data);
61 /* drag motion callback on initiator */
62
63 static void OperationChanged(Widget dc, Flight flight,
64 XmOperationChangedCallbackStruct *call_data);
65 /* side effect change callback on initiator */
66
67 static void PlaneLanding(Widget dc, Flight flight,
68 XmDropStartCallbackStruct *call_data);
69 /* drop start callback on initiator side */
70
71 static void PlaneHasLanded(Widget dc, Flight flight,
72 XmDropFinishCallbackStruct *call_data);
73 /* drop end callback on initiator side */
74
75 static void FlightFinished(Widget dc, Flight flight,
76 XmDragDropFinishCallback *call_data);
77 /* drag drop finish callback on initiator. Remove data for that plane */
78
79 static Boolean SendPlaneID(Widget drag_context, Atom *selection, Atom *target,
80 Atom *type,
81 XtPointer *value, unsigned long *length,
82 int *format);
83
84 /* The Xt selection convert proc sending the data to the drop site */
85
86
87 /* ===============================================================
88 * Start dragging a plane icon.
89 */
90
TakeOff(Widget area,Airport this,XButtonEvent * evt,int spot)91 void TakeOff(Widget area, Airport this, XButtonEvent *evt, int spot)
92 {
93 Arg args[20];
94 int n;
95 Flight flight;
96 Widget dc;
97 char msg[256];
98 static Boolean init = True;
99
100 if (init) {
101 srand((unsigned int) XtWindow(area));
102 init = False;
103 }
104
105 flight = (Flight)XtCalloc(sizeof(FlightRec), 1);
106 flight->number = rand();
107 flight->from = this;
108 flight->gate = spot;
109 sprintf(msg, "Flight %ld leaving from gate %d",
110 flight->number, flight->gate);
111 Paging(this, msg);
112 n = 0;
113 XtSetArg(args[n], XmNclientData, flight); n++;
114 XtSetArg(args[n], XmNconvertProc, SendPlaneID); n++;
115 XtSetArg(args[n], XmNcursorBackground,
116 AirportResources.flight_background); n++;
117 XtSetArg(args[n], XmNcursorForeground,
118 AirportResources.flight_foreground); n++;
119 XtSetArg(args[n], XmNvalidCursorForeground,
120 AirportResources.valid_foreground); n++;
121 XtSetArg(args[n], XmNinvalidCursorForeground,
122 AirportResources.invalid_foreground); n++;
123 XtSetArg(args[n], XmNnoneCursorForeground,
124 AirportResources.none_foreground); n++ ;
125 XtSetArg(args[n], XmNdragOperations, XmDROP_MOVE) ; n++;
126 XtSetArg(args[n], XmNblendModel, XmBLEND_JUST_SOURCE) ; n++;
127 XtSetArg(args[n], XmNsourceCursorIcon, this->dragIcon) ; n++;
128 XtSetArg(args[n], XmNexportTargets, &FlightAtom); n++;
129 XtSetArg(args[n], XmNnumExportTargets, 1); n++;
130 dc = XmDragStart(area, (XEvent *)evt, args, n);
131 XtAddCallback(dc, XmNdragMotionCallback,
132 (XtCallbackProc) Flying, (XtPointer) this);
133 XtAddCallback(dc, XmNdropSiteEnterCallback,
134 (XtCallbackProc) DropSiteEnter, (XtPointer) this);
135 XtAddCallback(dc, XmNdropSiteLeaveCallback,
136 (XtCallbackProc) DropSiteLeave, (XtPointer) this);
137 XtAddCallback(dc, XmNtopLevelEnterCallback,
138 (XtCallbackProc) EnterTopLevel, (XtPointer) this);
139 XtAddCallback(dc, XmNtopLevelLeaveCallback,
140 (XtCallbackProc) LeaveTopLevel, (XtPointer) this);
141 XtAddCallback(dc, XmNdropStartCallback,
142 (XtCallbackProc) PlaneLanding, (XtPointer) flight);
143 XtAddCallback(dc, XmNdropFinishCallback,
144 (XtCallbackProc) PlaneHasLanded, (XtPointer) flight);
145 XtAddCallback(dc, XmNdragDropFinishCallback,
146 (XtCallbackProc) FlightFinished , (XtPointer) flight);
147 XtAddCallback(dc, XmNoperationChangedCallback,
148 (XtCallbackProc) OperationChanged, (XtPointer) flight);
149
150 }
151
152 /* ===============================================================
153 * Pointer enters a new top level window.
154 * Check if this is the ocean or new land
155 */
156
EnterTopLevel(Widget dc,Airport this,XmTopLevelEnterCallbackStruct * call_data)157 static void EnterTopLevel(Widget dc, Airport this,
158 XmTopLevelEnterCallbackStruct *call_data)
159 {
160
161 if (call_data->window != this->ocean)
162 XmToggleButtonSetState(this->from.over_land, True, True);
163 }
164
165 /* ===============================================================
166 * Pointer leaves current top level window.
167 * Assume we are back on the ocean. Next enter will reset the right value.
168 */
169
LeaveTopLevel(Widget dc,Airport this,XmTopLevelLeaveCallbackStruct * call_data)170 static void LeaveTopLevel(Widget dc, Airport this,
171 XmTopLevelLeaveCallbackStruct *call_data)
172 {
173 XmToggleButtonSetState(this->from.over_ocean, True, True);
174 }
175
176 /* ===============================================================
177 * Someone is entering over the airport.
178 * Signal radar detection.
179 */
180
DropSiteEnter(Widget dc,Airport this,XmDropSiteEnterCallbackStruct * call_data)181 static void DropSiteEnter(Widget dc, Airport this,
182 XmDropSiteEnterCallbackStruct *call_data)
183 {
184 XmToggleButtonSetState(this->from.over_site, True, True);
185 }
186
187 /* ===============================================================
188 * The thing that was over is leaving the airport.
189 * Radar contact lost.
190 */
191
DropSiteLeave(Widget dc,Airport this,XmDropSiteLeaveCallbackStruct * call_data)192 static void DropSiteLeave(Widget dc, Airport this,
193 XmDropSiteLeaveCallbackStruct *call_data)
194 {
195 XmToggleButtonSetState(this->from.over_land, True, True);
196 }
197
198 /* ===============================================================
199 * Motion callback on source side.
200 * This is where we would could do fancy animation of the source icon.
201 * Here we just beep.
202 */
203
Flying(Widget dc,Airport this,XmDragMotionCallbackStruct * call_data)204 static void Flying(Widget dc, Airport this,
205 XmDragMotionCallbackStruct *call_data)
206 {
207 static Boolean first = True;
208
209 if (first)
210 {
211 XKeyboardControl controlValues;
212 unsigned long valueMask = KBBellPercent | KBBellPitch | KBBellDuration;
213
214 controlValues.bell_percent = AirportResources.bell_percent;
215 controlValues.bell_pitch = 440;
216 controlValues.bell_duration = AirportResources.bell_duration;
217 XChangeKeyboardControl(this->display, valueMask, &controlValues);
218 first = False;
219 }
220
221 XBell(this->display, 100);
222
223 }
224
225 /* ===============================================================
226 * The drop start callback on the source side.
227 * Set state to plane landing
228 */
229
PlaneLanding(Widget dc,Flight flight,XmDropStartCallbackStruct * call_data)230 static void PlaneLanding(Widget dc, Flight flight,
231 XmDropStartCallbackStruct *call_data)
232 {
233 XmToggleButtonSetState(flight->from->from.landing, True, True);
234 }
235
236
237 /* ===============================================================
238 * The operation changed callback. Planes only move, no copy
239 */
240
OperationChanged(Widget dc,Flight flight,XmOperationChangedCallbackStruct * call_data)241 static void OperationChanged(Widget dc, Flight flight,
242 XmOperationChangedCallbackStruct *call_data)
243 {
244
245 }
246
247 /* ===============================================================
248 * The drop finish callback. The plane has landed somewhere
249 * Hold on, it's not finished yet
250 */
251
PlaneHasLanded(Widget dc,Flight flight,XmDropFinishCallbackStruct * call_data)252 static void PlaneHasLanded(Widget dc, Flight flight,
253 XmDropFinishCallbackStruct *call_data)
254 {
255 Airport this = flight->from;
256 char msg[256];
257
258 XmToggleButtonSetState(this->from.landed, True, True);
259
260 if (call_data->completionStatus == XmDROP_SUCCESS) {
261 Spot spot = &(this->park.spots[flight->gate]);
262
263 spot->empty = True;
264 XClearArea(this->display, XtWindow(this->airport),
265 spot->x, spot->y, plane_width, plane_height, False);
266 sprintf(msg, "Passengers from flight %ld have landed safely",
267 flight->number);
268 }
269 else
270 sprintf(msg, "Flight %ld has returned", flight->number);
271 Paging(this, msg);
272 }
273
274 /* ===============================================================
275 * the drag drop finish callback. Clean data structures.
276 */
277
FlightFinished(Widget dc,Flight flight,XmDragDropFinishCallback * call_data)278 static void FlightFinished(Widget dc, Flight flight,
279 XmDragDropFinishCallback *call_data)
280 {
281 Airport this = flight->from;
282
283 XmToggleButtonSetState(this->from.departure, True, True);
284 XtFree((char *) flight);
285 }
286 /* ===============================================================
287 * Xt convert selection proc.
288 * Send flight ID on drop transfer request.
289 * Delete the source plane image on Delete. You know it's arrived there.
290 */
291
SendPlaneID(Widget drag_context,Atom * selection,Atom * target,Atom * type,XtPointer * value,unsigned long * length,int * format)292 static Boolean SendPlaneID(Widget drag_context, Atom *selection, Atom *target,
293 Atom *type,
294 XtPointer *value, unsigned long *length,
295 int *format)
296 {
297 Airport this;
298 Flight flight;
299
300 XtVaGetValues(drag_context, XmNclientData, &flight, NULL);
301 this = flight->from;
302
303 if (*target == FlightAtom) {
304 long * data = (long *) XtMalloc(sizeof(long));
305
306 *data = flight->number;
307 *type = FlightAtom;
308 *value = (XtPointer) data;
309 *format = 32;
310 *length = 1;
311 return True;
312 }
313 else {
314 Paging(flight->from, "Erroneous messsage on radio");
315 return False;
316 }
317 }
318