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