]> git.mxchange.org Git - flightgear.git/blob - src/ATC/ATCDialog.cxx
0bb9ce5b2eb167bca60d44ff92e38cabf2832877
[flightgear.git] / src / ATC / ATCDialog.cxx
1 // ATCDialog.cxx - Functions and classes to handle the pop-up ATC dialog
2 //
3 // Written by Alexander Kappes and David Luff, started February 2003.
4 //
5 // Copyright (C) 2003  Alexander Kappes and David Luff
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 #include <simgear/compiler.h>
22
23 #include <simgear/structure/commands.hxx>
24
25 #include <Main/globals.hxx>
26 #include <GUI/gui.h>
27
28 #include "ATCDialog.hxx"
29 #include "ATC.hxx"
30 #include "ATCmgr.hxx"
31 #include "commlist.hxx"
32 #include "ATCutils.hxx"
33 #include <Airports/simple.hxx>
34
35 #include <sstream>
36
37 SG_USING_STD(ostringstream);
38
39 FGATCDialog *current_atcdialog;
40
41 // For the command manager - maybe eventually this should go in the built in command list
42 static bool do_ATC_dialog(const SGPropertyNode* arg) {
43         globals->get_ATC_mgr()->doPopupDialog();
44         return(true);
45 }
46
47 static bool do_ATC_freq_search(const SGPropertyNode* arg) {
48         current_atcdialog->FreqDialog();
49         return(true);
50 }
51
52 ATCMenuEntry::ATCMenuEntry() {
53   stationid    = "";
54   stationfr    = 0;
55   transmission = "";
56   menuentry    = "";
57 }
58
59 ATCMenuEntry::~ATCMenuEntry() {
60 }
61
62 static char* t0 = "No communication currently available";
63 //static char* t1 = "Request departure clearance";
64 //static char* t2 = "Report Runway vacated";
65 static char** towerOptions = new char*[2];
66
67 // ----------------------- DCL ------------------------------------------
68 // For the ATC dialog - copied from the Autopilot new heading dialog code!
69 static puDialogBox*             atcDialog;
70 static puFrame*                 atcDialogFrame;
71 static puText*                  atcDialogMessage;
72 //static puInput*                       atcDialogInput;
73 static puOneShot*               atcDialogOkButton;
74 static puOneShot*               atcDialogCancelButton;
75 static puButtonBox*             atcDialogCommunicationOptions;
76 // ----------------------------------------------------------------------
77
78 // ------------------------ AK ------------------------------------------
79 static puDialogBox  *ATCMenuBox = 0;
80 static puFrame      *ATCMenuFrame = 0;
81 static puText       *ATCMenuBoxMessage = 0;
82 static puButtonBox      *ATCOptionsList = 0;
83 // ----------------------------------------------------------------------
84
85 // AK
86 static void AKATCDialogOK(puObject *)
87 {
88         switch(ATCOptionsList->getValue()) {
89         case 0:
90                 //cout << "Option 0 chosen\n";
91                 fgSetBool("/sim/atc/opt0",true);
92                 break;
93         case 1:
94                 //cout << "Option 1 chosen\n";
95                 fgSetBool("/sim/atc/opt1",true);
96                 break;
97         case 2:
98                 //cout << "Option 2 chosen\n";
99                 fgSetBool("/sim/atc/opt2",true);
100                 break;
101         case 3:
102                 //cout << "Option 2 chosen\n";
103                 fgSetBool("/sim/atc/opt3",true);
104                 break;
105         default:
106                 break;
107         }
108         FG_POP_PUI_DIALOG( ATCMenuBox );
109 }
110
111 // AK
112 static void AKATCDialogCancel(puObject *)
113 {
114     FG_POP_PUI_DIALOG( ATCMenuBox );
115 }
116
117 // DCL
118 static void ATCDialogCancel(puObject *)
119 {
120     //ATCDialogInput->rejectInput();
121     FG_POP_PUI_DIALOG( atcDialog );
122 }
123
124 // DCL
125 static void ATCDialogOK (puObject *me)
126 {
127         // Note that currently the dialog is hardwired to comm1 only here.
128         switch(globals->get_ATC_mgr()->GetComm1ATCType()) {
129         case INVALID:
130                 break;
131         case ATIS:
132                 break;
133         case TOWER: {
134                 /*
135                 FGTower* twr = (FGTower*)globals->get_ATC_mgr()->GetComm1ATCPointer();
136                 switch(atcDialogCommunicationOptions->getValue()) {
137                 case 0:
138                         //cout << "Option 0 chosen\n";
139                         twr->RequestLandingClearance("charlie foxtrot sierra");
140                         break;
141                 case 1:
142                         //cout << "Option 1 chosen\n";
143                         twr->RequestDepartureClearance("charlie foxtrot sierra");
144                         break;
145                 case 2:
146                         //cout << "Option 2 chosen\n";
147                         twr->ReportRunwayVacated("charlie foxtrot sierra");
148                         break;
149                 default:
150                         break;
151                 }
152                 */
153                 break;
154         }
155         case GROUND:
156                 break;
157         case APPROACH:
158                 break;
159         default:
160                 break;
161         }
162
163     ATCDialogCancel(me);
164     //if(error) mkDialog(s.c_str());
165 }
166
167 // DCL
168 static void ATCDialog(puObject *cb)
169 {
170     //ApHeadingDialogInput   ->    setValue ( heading );
171     //ApHeadingDialogInput    -> acceptInput();
172     FG_PUSH_PUI_DIALOG(atcDialog);
173 }
174
175 // DCL
176 void ATCDialogInit()
177 {
178         char defaultATCLabel[] = "Enter desired option to communicate with ATC:";
179         char *s;
180
181         // Option lists hardwired per ATC type  
182         towerOptions[0] = new char[strlen(t0)+1];
183         strcpy(towerOptions[0], t0);
184         //towerOptions[1] = new char[strlen(t1)+1];
185         //strcpy(towerOptions[1], t1);
186         //towerOptions[2] = new char[strlen(t2)+1];
187         //strcpy(towerOptions[2], t2);
188         towerOptions[1] = NULL;
189         
190         atcDialog = new puDialogBox (150, 50);
191         {
192                 atcDialogFrame   = new puFrame (0, 0, 500, 250);
193                 
194                 atcDialogMessage = new puText          (250, 220);
195                 atcDialogMessage    -> setDefaultValue (defaultATCLabel);
196                 atcDialogMessage    -> getDefaultValue (&s);
197                 atcDialogMessage    -> setLabel        (s);
198                 atcDialogMessage    -> setLabelPlace   (PUPLACE_TOP_CENTERED);
199
200                 atcDialogCommunicationOptions = new puButtonBox (50, 50, 450, 210, NULL, true);
201                 
202                 atcDialogOkButton     =  new puOneShot         (50, 10, 110, 50);
203                 atcDialogOkButton     ->     setLegend         (gui_msg_OK);
204                 atcDialogOkButton     ->     makeReturnDefault (TRUE);
205                 atcDialogOkButton     ->     setCallback       (ATCDialogOK);
206                 
207                 atcDialogCancelButton =  new puOneShot         (140, 10, 210, 50);
208                 atcDialogCancelButton ->     setLegend         (gui_msg_CANCEL);
209                 atcDialogCancelButton ->     setCallback       (ATCDialogCancel);
210                 
211         }
212         FG_FINALIZE_PUI_DIALOG(atcDialog);
213         
214         // Add ATC-dialog to the command list
215         globals->get_commands()->addCommand("ATC-dialog", do_ATC_dialog);
216 }
217
218 ///////////////////////////////////////////////////////////////////////
219 //
220 // ATCDoDialog is in a state of flux at the moment
221 // Stations other than approach are handled by DCL's simple code
222 // Approach is handled by AK's fancy dynamic-list code
223 // Hopefully all interactive stations should go to AK's code eventually
224 //
225 ///////////////////////////////////////////////////////////////////////
226 void ATCDoDialog(atc_type type) {
227         switch(type) {
228         case INVALID:
229                 atcDialogCommunicationOptions->newList(NULL);
230                 atcDialogMessage->setLabel("Not tuned in to any ATC service.");
231                 break;
232         case ATIS:
233                 atcDialogCommunicationOptions->newList(NULL);
234                 atcDialogMessage->setLabel("Tuned in to ATIS: no communication possible.");
235                 break;
236         case TOWER: 
237                 atcDialogCommunicationOptions->newList(towerOptions);
238                 atcDialogMessage->setLabel("Tuned in to Tower - select communication to transmit:");
239                 break;
240         case GROUND:
241                 atcDialogCommunicationOptions->newList(NULL);
242                 atcDialogMessage->setLabel("Tuned in to Ground - select communication to transmit:");
243                 break;
244         case APPROACH:
245                 current_atcdialog->DoDialog();
246                 break;
247         default:
248                 atcDialogCommunicationOptions->newList(NULL);
249                 atcDialogMessage->setLabel("Tuned in to unknown ATC service - enter transmission:");
250                 break;
251         }
252
253         // Third - display the dialog without pausing sim.
254         if(type != APPROACH) {  
255                 ATCDialog(NULL);
256         }
257 }
258
259 void FGATCDialog::Init() {
260         // Add ATC-freq-search to the command list
261         globals->get_commands()->addCommand("ATC-freq-search", do_ATC_freq_search);
262 }
263
264 // AK
265 // Add an entry
266 void FGATCDialog::add_entry(string station, string transmission, string menutext ) {
267   
268   ATCMenuEntry a;
269
270   a.stationid = station;
271   a.transmission = transmission;
272   a.menuentry = menutext;
273
274   atcmentrylist_station[station.c_str()].push_back(a);
275
276 }
277
278 // AK
279 // query the database whether the transmission is already registered; 
280 bool FGATCDialog::trans_reg( const string &station, const string &trans ) {
281
282   atcmentry_list_type     atcmlist = atcmentrylist_station[station];
283   atcmentry_list_iterator current  = atcmlist.begin();
284   atcmentry_list_iterator last     = atcmlist.end();
285   
286   for ( ; current != last ; ++current ) {
287     if ( current->transmission == trans ) return true;
288   }
289   return false;
290 }
291
292 // AK
293 // ===================================================
294 // ===  Update ATC menue and look for keys pressed ===
295 // ===================================================
296 void FGATCDialog::DoDialog() {
297         
298         static string mentry[10];
299         static string mtrans[10];
300         char   buf[10];
301         TransPar TPar;
302         FGATC* atcptr = globals->get_ATC_mgr()->GetComm1ATCPointer();   // Hardwired to comm1 at the moment
303         
304         if(atcptr != NULL) {
305                 
306                 atcmentry_list_type     atcmlist = atcmentrylist_station[atcptr->get_ident()];
307                 //atcmentry_list_type     atcmlist = atcmentrylist_station["EGNX"];
308                 atcmentry_list_iterator current  = atcmlist.begin();
309                 atcmentry_list_iterator last     = atcmlist.end();
310                 
311                 // Set all opt flags to false before displaying box
312                 fgSetBool("/sim/atc/opt0",false);
313                 fgSetBool("/sim/atc/opt1",false);
314                 fgSetBool("/sim/atc/opt2",false);
315                 fgSetBool("/sim/atc/opt3",false);
316                 fgSetBool("/sim/atc/opt4",false);
317                 fgSetBool("/sim/atc/opt5",false);
318                 fgSetBool("/sim/atc/opt6",false);
319                 fgSetBool("/sim/atc/opt7",false);
320                 fgSetBool("/sim/atc/opt8",false);
321                 fgSetBool("/sim/atc/opt9",false);
322                 
323                 //int yc = 10;
324                 int yc = 70;
325                 int xsize = 600;
326                 
327                 if ( atcmlist.size() != 0 ){ 
328                         int k=atcmlist.size();
329                         //int k = 3;
330                         //cout << "k = " << k << endl;
331                         int y = (fgGetInt("/sim/startup/ysize") - 200 - 20 - k*20);
332                         ATCMenuBox = new puDialogBox (100, y);
333                         ATCMenuFrame      =  new puFrame (0,0,xsize,yc+40);
334                         // loop over all entries in atcmentrylist
335                         ATCOptionsList = new puButtonBox (50, 50, 450, 50+(k*25), NULL, true);
336                         char** optList = new char*[k+1];
337                         int kk = 0;
338                         for ( ; current != last ; ++current ) {
339                                 string dum;
340                                 sprintf( buf, "%i", kk+1 );
341                                 buf[1] = '\0';
342                                 dum = buf;
343                                 mentry[kk] = dum + ". " + current->menuentry;
344                                 optList[kk] = new char[strlen(mentry[kk].c_str()) + 1];
345                                 strcpy(optList[kk], mentry[kk].c_str());
346                                 //cout << "optList[" << kk << "] = " << optList[kk] << endl; 
347                                 mtrans[kk] =              current->transmission;
348                                 //ATCMenuBoxMessage =  new puText (10, yc);
349                                 //ATCMenuBoxMessage ->     setLabel( mentry[kk].c_str() );
350                                 yc += 20;
351                                 ++kk;
352                         } 
353                         yc += 2*20;
354                         optList[k] = NULL;
355                         ATCOptionsList->newList(optList);
356                 } else {
357                         int y = (fgGetInt("/sim/startup/ysize") - 100 - 20 );
358                         ATCMenuBox = new puDialogBox (10, y);
359                         ATCMenuFrame      =  new puFrame (0,0,xsize,yc+40);
360                         ATCMenuBoxMessage =  new puText (10, yc-10);
361                         ATCMenuBoxMessage ->     setLabel( "No transmission available" );
362                 }
363                 
364                 ATCMenuBoxMessage =  new puText (10, yc+10);
365                 ATCMenuBoxMessage ->     setLabel( "ATC Menu" );
366                 atcDialogOkButton     =  new puOneShot         ((xsize/2)-85, 10, (xsize/2)-25, 50);
367                 atcDialogOkButton     ->     setLegend         (gui_msg_OK);
368                 atcDialogOkButton     ->     makeReturnDefault (TRUE);
369                 atcDialogOkButton     ->     setCallback       (AKATCDialogOK);
370                 
371                 atcDialogCancelButton =  new puOneShot         ((xsize/2)+25, 10, (xsize/2)+85, 50);
372                 atcDialogCancelButton ->     setLegend         (gui_msg_CANCEL);
373                 atcDialogCancelButton ->     setCallback       (AKATCDialogCancel);
374                 FG_FINALIZE_PUI_DIALOG( ATCMenuBox );
375                 FG_PUSH_PUI_DIALOG( ATCMenuBox );
376                 
377                 
378                 /*      
379                 if ( atckey != -1 && TransDisplayed && mtrans[atckey-1].c_str() != "" ) {
380                         cout << mtrans[atckey-1].c_str() << endl;
381                         TPar = current_transmissionlist->extract_transpar( mtrans[atckey-1].c_str() );
382                         current_atcmentrylist->reset = true;
383                         current_transparlist->add_entry( TPar );
384                         
385                         //    transpar_list_type test = current_transparlist;
386                         // transpar_list_iterator current = test.begin();
387                         //for ( ; current != test.end(); ++current ) {
388                                 // current->tpar.intention;
389                         //}
390                 }
391                 
392                 if ( current_atcmentrylist->freq != (int)(comm1_freq*100.0 + 0.5) ) {
393                         current_atcmentrylist->reset = true;
394                 }
395                 
396                 // reset (delete) ATCmenue list if reset is true
397                 if ( current_atcmentrylist->reset == true ) {
398                         delete ( current_atcmentrylist );
399                         current_atcmentrylist = new FGatcmentryList;
400                         current_atcmentrylist->init( (int)(comm1_freq*100.0 + 0.5) );
401                         if ( TransDisplayed ) {
402                                 FG_POP_PUI_DIALOG( ATCMenuBox ); 
403                                 TransDisplayed = false;
404                         }
405                 }
406                 */      
407         }
408 }
409
410 //////////////////////////////////////////////////////
411 //
412 //  STUFF FOR THE FREQUENCY SEARCH DIALOG
413 //
414 //////////////////////////////////////////////////////
415
416 static puDialogBox*     atcFreqDialog;
417 static puFrame*         atcFreqDialogFrame;
418 static puText*          atcFreqDialogMessage;
419 static puInput*         atcFreqDialogInput;
420 static puOneShot*       atcFreqDialogOkButton;
421 static puOneShot*       atcFreqDialogCancelButton;
422
423 static puDialogBox*     atcFreqDisplay;
424 static puFrame*         atcFreqDisplayFrame;
425 static puText*          atcFreqDisplayMessage;
426 static puOneShot*       atcFreqDisplayOkButton;
427 static puOneShot*       atcFreqDisplayCancelButton;
428 static puText*          atcFreqDisplayText[20];
429         
430 static void FreqDialogCancel(puObject*) {
431         FG_POP_PUI_DIALOG(atcFreqDialog);
432 }
433
434 static void FreqDialogOK(puObject*) {
435         string tmp = atcFreqDialogInput->getStringValue();
436         FG_POP_PUI_DIALOG(atcFreqDialog);
437         current_atcdialog->FreqDisplay(tmp);
438 }
439
440 static void FreqDisplayOK(puObject*) {
441         FG_POP_PUI_DIALOG(atcFreqDisplay);
442 }
443
444 static void FreqDisplayCancel(puObject*) {
445         FG_POP_PUI_DIALOG(atcFreqDisplay);
446 }
447
448 void FGATCDialog::FreqDialog() {
449
450         // Find the ATC stations within a reasonable range (about 40 miles?)
451         //comm_list_type atc_stations;
452         //comm_list_iterator atc_stat_itr;
453         
454         //double lon = fgGetDouble("/position/longitude-deg");
455         //double lat = fgGetDouble("/position/latitude-deg");
456         //double elev = fgGetDouble("/position/altitude-ft");
457         
458         /*
459         // search stations in range
460         int num_stat = current_commlist->FindByPos(lon, lat, elev, 40.0, &atc_stations);
461         if (num_stat != 0) {
462         } else {
463                 // Make up a message saying no things in range
464         }
465         */
466         
467         //char defaultATCLabel[] = "Enter desired option to communicate with ATC:";
468         char *s;
469         
470         int hsize = 150;
471         atcFreqDialog = new puDialogBox (150, 50);
472         {
473                 atcFreqDialogFrame   = new puFrame (0, 0, 300, hsize);
474                 
475                 atcFreqDialogMessage = new puText          (40, (hsize - 30));
476                 atcFreqDialogMessage    -> setDefaultValue ("Enter airport identifier:");
477                 atcFreqDialogMessage    -> getDefaultValue (&s);
478                 atcFreqDialogMessage    -> setLabel        (s);
479
480                 atcFreqDialogInput = new puInput (50, (hsize - 75), 150, (hsize - 45));
481                 atcFreqDialogInput->acceptInput();
482                 
483                 atcFreqDialogOkButton     =  new puOneShot         (50, 10, 110, 50);
484                 atcFreqDialogOkButton     ->     setLegend         (gui_msg_OK);
485                 atcFreqDialogOkButton     ->     makeReturnDefault (TRUE);
486                 atcFreqDialogOkButton     ->     setCallback       (FreqDialogOK);
487                 
488                 atcFreqDialogCancelButton =  new puOneShot         (140, 10, 210, 50);
489                 atcFreqDialogCancelButton ->     setLegend         (gui_msg_CANCEL);
490                 atcFreqDialogCancelButton ->     setCallback       (FreqDialogCancel);
491                 
492         }
493         FG_FINALIZE_PUI_DIALOG(atcFreqDialog);
494         
495         FG_PUSH_PUI_DIALOG(atcFreqDialog);
496         
497 }
498
499 static void atcUppercase(string &s)
500 {
501         for(unsigned int i=0; i<s.size(); ++i) {
502                 s[i] = toupper(s[i]);
503         }
504 }
505
506 void FGATCDialog::FreqDisplay(string ident) {
507
508         atcUppercase(ident);
509         
510         //char defaultATCLabel[] = "Enter desired option to communicate with ATC:";
511         string label = "Frequencies for airport ";
512         label += ident;
513         label += ":";
514         char *s;
515         
516         int n = 0;      // Number of ATC frequencies at this airport
517         string freqs[20];
518         char buf[8];
519
520     FGAirport a;
521     if ( dclFindAirportID( ident, &a ) ) {
522                 comm_list_type stations;
523                 int found = current_commlist->FindByPos(a.longitude, a.latitude, a.elevation, 20.0, &stations);
524                 if(found) {
525                         ostringstream ostr;
526                         comm_list_iterator itr = stations.begin();
527                         while(itr != stations.end()) {
528                                 if((*itr).ident == ident) {
529                                         if((*itr).type != INVALID) {
530                                                 ostr << (*itr).type;
531                                                 freqs[n] = ostr.str();
532                                                 freqs[n].append("     -     ");
533                                                 sprintf(buf, "%.2f", ((*itr).freq / 100.0));    // Convert from KHz to MHz
534                                                 // Hack alert!
535                                                 if(buf[5] == '3') buf[5] = '2';
536                                                 if(buf[5] == '8') buf[5] = '7';
537                                                 freqs[n] += buf;
538                                                 ostr.seekp(0);
539                                                 n++;
540                                         }
541                                 }
542                                 ++itr;
543                         }
544                 }
545     } else {
546                 label = "Airport ";
547                 label += ident;
548                 label += " not found in database.";
549                 n = -1;
550         }
551         
552         if(n == 0) {
553                 label = "No frequencies found for airport ";
554                 label += ident;
555         }
556
557         int hsize = (n < 0 ? 100 : 105 + (n * 30));
558         atcFreqDisplay = new puDialogBox (250, 50);
559         {
560                 atcFreqDisplayFrame   = new puFrame (0, 0, 400, hsize);
561                 
562                 atcFreqDisplayMessage = new puText          (40, (hsize - 30));
563                 atcFreqDisplayMessage    -> setDefaultValue (label.c_str());
564                 atcFreqDisplayMessage    -> getDefaultValue (&s);
565                 atcFreqDisplayMessage    -> setLabel        (s);
566                 
567                 for(int i=0; i<n; ++i) {
568                         atcFreqDisplayText[i] = new puText(40, hsize - 65 - (30 * i));
569                         atcFreqDisplayText[i]->setDefaultValue(freqs[i].c_str());
570                         atcFreqDisplayText[i]-> getDefaultValue (&s);
571                         atcFreqDisplayText[i]-> setLabel        (s);
572                 }
573                 
574                 atcFreqDisplayOkButton     =  new puOneShot         (50, 10, 110, 50);
575                 atcFreqDisplayOkButton     ->     setLegend         (gui_msg_OK);
576                 atcFreqDisplayOkButton     ->     makeReturnDefault (TRUE);
577                 atcFreqDisplayOkButton     ->     setCallback       (FreqDisplayOK);
578                 
579                 atcFreqDisplayCancelButton =  new puOneShot         (140, 10, 210, 50);
580                 atcFreqDisplayCancelButton ->     setLegend         (gui_msg_CANCEL);
581                 atcFreqDisplayCancelButton ->     setCallback       (FreqDisplayCancel);
582                 
583         }
584         FG_FINALIZE_PUI_DIALOG(atcFreqDisplay);
585         
586         FG_PUSH_PUI_DIALOG(atcFreqDisplay);
587         
588 }
589