1
/* $TOG: main.c /main/6 1997/03/31 13:47:48 dbl $ */
3
* @OPENGROUP_COPYRIGHT@
5
* Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
6
* Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
7
* ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
8
* the full copyright text.
10
* This software is subject to an open license. It may only be
11
* used on, with or for operating systems which are themselves open
12
* source systems. You must contact The Open Group for a license
13
* allowing distribution and sublicensing of this software on, with,
14
* or for operating systems which are not Open Source programs.
16
* See http://www.opengroup.org/openmotif/license for full
17
* details of the license agreement. Any use, reproduction, or
18
* distribution of the program constitutes recipient's acceptance of
21
* EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
22
* PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23
* KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
24
* WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
25
* OR FITNESS FOR A PARTICULAR PURPOSE
27
* EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
28
* NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
29
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
31
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33
* ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
34
* EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
35
* POSSIBILITY OF SUCH DAMAGES.
42
* The Airport Drag And Drop Demo
47
/* ============================ local constants ======================= */
51
/* ============================ prototypes ======================= */
53
static Widget MenuBarEntry(Widget menubar, String entry, String labels[],
54
XtCallbackProc procs[], XtPointer private[], int count);
56
static void HelpCallback(Widget button, Airport this, XtPointer cbs);
58
static void ExitCallback(Widget button, Airport this, XtPointer cbs);
60
static void ResizeAirport(Widget area, Airport this, XtPointer cbs);
61
/* resize callback of airport */
63
static void ShowAirport(Widget area, Airport this, XtPointer cbs);
64
/* expose callback of airport */
66
static void AirportInput(Widget area, Airport this, XtPointer cbs);
67
/* Callback when pointer or keyboard input in airport */
69
static void ConfigureAirport(Widget area, Airport this);
70
/* configure geometry */
72
static void Warning(Airport this, XmString s1, XmString s2);
73
/* issue a warning to user */
76
/* ==============================================================
81
main(int argc, char *argv[])
83
#define MAIN_CHILDREN 3
84
#define FORM_CHILDREN 3
85
#define PLANE_CHILDREN 6
86
#define TRAFFIC_CHILDREN 3
87
#define SetMenuEntry(k,l,p,d) labels[k]=l;procs[k]=p;private[k]=d;
93
Widget main_tab[MAIN_CHILDREN];
94
Widget from_tab[PLANE_CHILDREN];
95
Widget to_tab[TRAFFIC_CHILDREN];
96
Widget form_tab[FORM_CHILDREN];
99
static char myClass[] = "XmdAirport";
103
XtCallbackProc procs[4];
104
XtPointer private[4];
112
this = (Airport) XtCalloc(sizeof(AirportRec), 1);
114
XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL);
116
theWidgetRoot = XtVaOpenApplication( &this->context,
123
sessionShellWidgetClass,
124
XmNallowShellResize, True,
127
this->display = XtDisplay(theWidgetRoot);
128
FlightAtom = XmInternAtom(this->display, "FLIGHT", False);
129
DeleteAtom = XmInternAtom(this->display, "DELETE", False);
131
XtGetApplicationResources(theWidgetRoot, &AirportResources,
132
AirportResourcesSpecs,
133
XtNumber(AirportResourcesSpecs),
137
* Create the Main Window, the menubar and the pulldown menus
140
this->main = XmCreateMainWindow(theWidgetRoot, "main", args, n);
143
main_tab[0] = XmCreateMenuBar(this->main, "menubar", args, n);
145
SetMenuEntry(n, "Exit",
146
(XtCallbackProc) ExitCallback, (XtPointer) this ); n++;
147
entry = MenuBarEntry(main_tab[0], "File", labels, procs, private, n);
149
SetMenuEntry(0, "Tutorial",
150
(XtCallbackProc) HelpCallback, (XtPointer) this); n++;
151
entry = MenuBarEntry(main_tab[0], "Help", labels, procs, private, n);
153
XtSetArg(args[n], XmNmenuHelpWidget, entry); n++;
154
XtSetValues(main_tab[0], args, n);
157
* Create the Airport widget structure.
158
* Two framed radio boxes show state.
159
* A drawing area in the middle show track and planes
163
this->screen_width = WidthOfScreen(XtScreenOfObject(this->main));
164
this->screen_height = HeightOfScreen(XtScreenOfObject(this->main));
165
XtSetArg(args[n], XmNwidth, this->screen_width*3/7); n++;
166
XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
167
main_tab[1] = XmCreateForm(this->main, "airport", args, n);
170
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
171
XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM); n++;
172
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM) ; n++;
173
form_tab[0] = XmCreateFrame(main_tab[1], "flight", args, n);
176
XtSetArg(args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
177
framed[0] = XmCreateLabel(form_tab[0], "title", args, n);
180
XtSetArg(args[n], XmNchildType, XmFRAME_WORKAREA_CHILD); n++;
181
XtSetArg(args[n], XmNresizePolicy, XmRESIZE_GROW); n++;
182
XtSetArg(args[n], XmNradioBehavior, True); n++;
183
framed[1] = XmCreateRadioBox(form_tab[0], "panel", args, n);
186
XtSetArg(args[n], XmNset, True); n++;
187
XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
188
this->from.departure =
189
from_tab[0] = XmCreateToggleButton(framed[1],
190
"departure", args, n);
192
XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
193
this->from.over_ocean =
194
from_tab[1] = XmCreateToggleButton(framed[1],
195
"over_ocean", args, n);
197
XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
198
this->from.over_land =
199
from_tab[2] = XmCreateToggleButton(framed[1],
200
"over_land", args, n);
202
XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
203
this->from.over_site =
204
from_tab[3] = XmCreateToggleButton(framed[1],
207
XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
209
from_tab[4] = XmCreateToggleButton(framed[1], "landing", args, n);
212
XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
214
from_tab[5] = XmCreateToggleButton(framed[1], "landed", args, n);
215
XtManageChildren(from_tab, PLANE_CHILDREN);
216
XtManageChildren(framed, 2);
219
* Create the Airport Traffic control state
223
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
224
XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM); n++;
225
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM) ; n++;
226
form_tab[1] = XmCreateFrame(main_tab[1], "traffic", args, n);
229
XtSetArg(args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
230
framed[0] = XmCreateLabel(form_tab[1], "title", args, n);
233
XtSetArg(args[n], XmNchildType, XmFRAME_WORKAREA_CHILD); n++;
234
XtSetArg(args[n], XmNradioBehavior, True); n++;
235
framed[1] = XmCreateRadioBox(form_tab[1], "traffic_box", args, n);
238
XtSetArg(args[n], XmNset, True); n++;
239
XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
241
to_tab[1] = XmCreateToggleButton(framed[1],
242
"no_traffic", args, n);
244
XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
246
to_tab[0] = XmCreateToggleButton(framed[1],
247
"radar_echo", args, n);
249
XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
251
to_tab[2] = XmCreateToggleButton(framed[1],
254
XtManageChildren(to_tab, TRAFFIC_CHILDREN);
255
XtManageChildren(framed, 2);
258
* Create the Airport picture
261
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
262
XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM); n++;
263
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET) ; n++;
264
XtSetArg(args[n], XmNleftWidget, form_tab[0]) ; n++;
265
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET) ; n++;
266
XtSetArg(args[n], XmNrightWidget, form_tab[1]) ; n++;
268
form_tab[2] = XmCreateDrawingArea(main_tab[1], "da", args, n);
269
XtAddCallback(this->airport, XmNexposeCallback,
270
(XtCallbackProc) ShowAirport, (XtPointer) this);
271
XtAddCallback(this->airport, XmNresizeCallback,
272
(XtCallbackProc) ResizeAirport, (XtPointer) this);
273
XtAddCallback(this->airport, XmNinputCallback,
274
(XtCallbackProc) AirportInput, (XtPointer) this);
276
* Create the Airport Message area
280
main_tab[2] = XmCreateFrame(this->main, "message", args, n);
283
XtSetArg(args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
284
framed[0] = XmCreateLabel(main_tab[2], "title", args, n);
287
XtSetArg(args[n], XmNchildType, XmFRAME_WORKAREA_CHILD); n++;
288
XtSetArg(args[n], XmNvisibleItemCount, 4); n++;
289
this->msg_area = XmCreateScrolledList(main_tab[2], "msg_list", args, n);
290
XtManageChild(this->msg_area);
291
framed[1] = XtParent(this->msg_area);
292
XtManageChildren(framed, 2);
295
XtSetArg(args[n], XmNmenuBar, main_tab[0]); n++;
296
XtSetArg(args[n], XmNworkWindow, main_tab[1]); n++;
297
XtSetArg(args[n], XmNmessageWindow, main_tab[2]); n++;
298
XtSetValues(this->main, args, n);
299
XtManageChildren(form_tab, FORM_CHILDREN);
300
XtManageChildren(main_tab, MAIN_CHILDREN);
301
XtManageChild(this->main);
303
XtRealizeWidget(theWidgetRoot);
306
* Create the drag icon
309
parked = XCreateBitmapFromData(this->display,
310
XtWindow(this->main), (char*)plane_bits,
311
plane_width, plane_height);
313
flying = XCreateBitmapFromData(this->display,
314
XtWindow(this->main), (char*)flying_bits,
315
flying_icon_width, flying_icon_height);
317
mask = XCreateBitmapFromData(this->display,
318
XtWindow(this->main), (char*)flying_mask_bits,
319
flying_mask_width, flying_mask_height);
321
XtSetArg(args[n], XmNpixmap, flying); n++;
322
XtSetArg(args[n], XmNdepth, 1); n++;
323
XtSetArg(args[n], XmNmask, mask); n++;
324
XtSetArg(args[n], XmNwidth, flying_icon_width); n++;
325
XtSetArg(args[n], XmNheight, flying_icon_height) ; n++;
326
this->dragIcon = XmCreateDragIcon(form_tab[2], "drag", args, n);
327
if (this->dragIcon == NULL) {
328
printf("cannot create drag icon\n");
331
/* Create GC for drawing planes */
332
gcv.function = GXcopy;
333
gcv.fill_style = FillOpaqueStippled;
334
gcv.stipple = parked;
335
gcv.foreground = AirportResources.spot_foreground;
336
gcv.background = AirportResources.spot_background;
337
this->park.gc = XCreateGC(this->display, XtWindow(this->main),
338
GCFunction|GCStipple|GCFillStyle
339
|GCForeground|GCBackground,
342
gcv.line_style = LineDoubleDash;
343
gcv.line_width = AirportResources.track_border_width;
344
gcv.fill_style = FillSolid;
345
gcv.foreground = AirportResources.track_foreground;
346
gcv.background = AirportResources.track_background;
347
this->track.gc = XCreateGC(this->display, XtWindow(this->main),
348
GCFunction|GCLineWidth|GCLineStyle
349
|GCFillStyle|GCForeground|GCBackground,
351
XtAppMainLoop(this->context);
353
return 0; /* make compiler happy */
356
/* ===============================================================
357
* Create a cascade and a pulldown entry into a menubar,
358
* from a list of push button specs.
359
* If the label is NULL, create a separator instead of a push button.
362
static Widget MenuBarEntry(Widget menubar, String entry, String labels[],
363
XtCallbackProc procs[], XtPointer private[],
374
menu = XmCreatePulldownMenu(menubar,
375
strcat(strcpy(name, entry), "Menu"),
377
for( i = 0; i < count; i++) {
379
if (labels[i] == NULL) {
380
child = XmCreateSeparator(menu, "sep", args, n);
383
child = XmCreatePushButton(menu, labels[i], args, n);
384
if (procs[i] != NULL)
385
XtAddCallback(child, XmNactivateCallback, procs[i], private[i]);
387
XtManageChild(child);
390
XtSetArg(args[n], XmNlabelString, XmStringCreateSimple(entry)); n++;
391
XtSetArg(args[n], XmNsubMenuId, menu); n++;
392
child = XmCreateCascadeButton(menubar, entry, args, n);
393
XtManageChild(child);
398
/* ===============================================================
399
* The Exit Callback. Exit properly.
402
static void ExitCallback(Widget button, Airport this, XtPointer cbs)
404
XtCloseDisplay(this->display);
408
/* ======================================================================
412
static void HelpCallback(Widget button, Airport this, XtPointer cbs)
414
static char helpmsg[] = "Read the README file, please...";
416
if ( this->help_dialog == NULL ) {
420
XtSetArg(args[n], XmNmessageString,
421
XmStringCreateLocalized(helpmsg)); n++;
422
this->help_dialog = XmCreateInformationDialog(button,
423
"helpdialog", args, n);
425
XtManageChild(this->help_dialog);
428
/* ===============================================================
429
* Create Airport tracks. Open airport to traffic.
433
static void ConfigureAirport(Widget area, Airport this)
437
Window root, parent, *wlist;
439
Dimension width, height;
440
int min_width, min_height;
443
* Try to make the screen background window the ocean.
444
* Be aware of running without a window manager,
445
* or with a reparenting window manager
446
* or a window manager like HP VUEWM who have a background window
449
this->ocean = (Window) NULL;
450
if (XQueryTree(this->display, XtWindow(XtParent(this->main)),
451
&root, &parent, &wlist, &count) != 0) {
455
XWindowAttributes wa;
457
current = this->ocean = parent;
458
if (XQueryTree(this->display, current, &root, &parent,
459
&wlist, &count) == 0)
464
/* beware of HP-VUE */
466
XGetWindowAttributes(this->display, wlist[0], &wa);
467
this->ocean = (wa.width >= this->screen_width
468
&& wa.height >= this->screen_height) ?
472
XGetWindowAttributes(this->display, current, &wa);
473
if (wa.width >= this->screen_width
474
&& wa.height >= this->screen_height)
476
this->ocean = current;
480
} while (root != current);
484
XtSetArg(args[n], XmNwidth, &width); n++;
485
XtSetArg(args[n], XmNheight, &height); n++;
486
XtGetValues(area, args, n);
488
if (this->state == open) { /* destroy current data */
489
XtFree((char *)this->park.spots);
490
XClearWindow(this->display, XtWindow(area) );
491
this->park.spot_count = 0;
493
min_height = AirportResources.track_margin * 4 + plane_height*2
494
+ AirportResources.track_border_width*2 + MIN_TRACK_SIZE;
495
min_width = AirportResources.track_margin*2 + plane_width ;
496
if ( min_height > (int) height || min_width > (int) width)
499
XmStringCreateLocalized(AirportResources.too_small),
501
this->state = closed;
507
this->track.bbox.x = (short) AirportResources.track_margin;
508
this->track.bbox.y = (short) AirportResources.track_margin*2
510
this->track.bbox.width = width - AirportResources.track_margin*2;
511
this->track.bbox.height = height - 2*this->track.bbox.y;
512
this->park.plane_count = (int) this->track.bbox.width / plane_width;
513
this->park.spot_count = 2 * this->park.plane_count;
514
this->park.spots = (Spot) XtCalloc(sizeof(SpotRec),
515
this->park.spot_count);
516
x = AirportResources.track_margin;
517
y = AirportResources.track_margin;
518
for (i = 0; i < this->park.plane_count ; i++) {
519
this->park.spots[i].empty = False;
520
this->park.spots[i].x = x ;
521
this->park.spots[i].y = y ;
525
x = AirportResources.track_margin;
526
y += this->track.bbox.y + this->track.bbox.height
527
+ AirportResources.track_margin;
528
for (i = this->park.plane_count; i < this->park.spot_count ; i++) {
529
this->park.spots[i].empty = True;
530
this->park.spots[i].x = x ;
531
this->park.spots[i].y = y ;
534
this->park.state = normal;
538
/* ===============================================================
539
* On Resize, clear the data structure and reset airport
540
* So the first time it is initialized.
543
static void ResizeAirport(Widget area, Airport this, XtPointer cbs)
546
if (! XtIsRealized(area) || this->state == closed)
548
ConfigureAirport(area, this);
552
/* ===============================================================
553
* Expose callback. Redraw the airport
555
static void ShowAirport(Widget area, Airport this, XtPointer cbs)
558
if (this->state == closed) {
559
ConfigureAirport(area, this);
560
MakeAirportDropSite(area, this);
563
DrawAirport(this, XtWindow(area), AirportResources.track_background,
564
AirportResources.track_foreground);
567
/* ===============================================================
568
* Input callback. On button 2 drag plane.
571
static void AirportInput(Widget area, Airport this, XtPointer cbs)
575
XmDrawingAreaCallbackStruct *call_data = (XmDrawingAreaCallbackStruct *)cbs;
577
if ((call_data->event->type != ButtonPress)
578
&& (call_data->event->type != ButtonRelease))
581
evt = (XButtonEvent *) call_data->event;
585
switch (evt->button) {
587
case Button2: /* start drag ?? */
589
for (i = 0; i < this->park.spot_count ; i++) {
590
if (evt->x >= this->park.spots[i].x
591
&& evt->y >= this->park.spots[i].y
592
&& evt->x <= this->park.spots[i].x + plane_width
593
&& evt->y <= this->park.spots[i].y + plane_height ) {
594
/* hit detection of the starting gate */
595
if (this->park.spots[i].empty == False)
596
TakeOff(area, this, evt, i);
612
/* ===============================================================
615
void DrawAirport(Airport this, Window wd, Pixel bg, Pixel fg)
620
XSetForeground(this->display, this->track.gc, fg);
621
XSetBackground(this->display, this->track.gc, bg);
622
XFillRectangle(this->display, wd, this->track.gc,
623
this->track.bbox.x, this->track.bbox.y,
624
this->track.bbox.width, this->track.bbox.height);
625
XDrawLine(this->display, wd, this->track.gc,
627
this->track.bbox.y + AirportResources.track_border_width,
628
this->track.bbox.x + this->track.bbox.width,
629
this->track.bbox.y + AirportResources.track_border_width);
630
y = this->track.bbox.y + this->track.bbox.height
631
- AirportResources.track_border_width;
632
XDrawLine(this->display, wd, this->track.gc,
633
this->track.bbox.x, y,
634
this->track.bbox.x + this->track.bbox.width, y);
636
for (i = 0; i < this->park.spot_count ; i++) {
637
if (this->park.spots[i].empty == False) {
638
XSetTSOrigin(this->display, this->park.gc,
639
this->park.spots[i].x, this->park.spots[i].y);
640
XFillRectangle(this->display, wd, this->park.gc,
641
this->park.spots[i].x, this->park.spots[i].y,
642
plane_width, plane_height);
647
/* ===============================================================
648
* Display a message in the message area
650
void Paging(Airport this, String msg)
654
item = XmStringCreateLocalized(msg);
655
XmListDeselectAllItems(this->msg_area);
656
XmListAddItem(this->msg_area, item, 0);
657
XmListSetBottomItem(this->msg_area, item);
660
/* =====================================================================
661
* Show application modal warning dialogue box with specified messages
664
static void Warning(Airport this, XmString s1, XmString s2)
673
msg = XmStringConcat(s1, s2);
675
if (this->warning_dialog == NULL) {
679
XtSetArg(args[n], XmNdialogStyle,
680
XmDIALOG_FULL_APPLICATION_MODAL);
682
this->warning_dialog = XmCreateWarningDialog(this->main,
685
XtVaSetValues(this->warning_dialog, XmNmessageString, msg, NULL);
686
XtManageChild(this->warning_dialog);