]> git.mxchange.org Git - flightgear.git/blob - src/ATC/ATCDialog.cxx
6b55eb7708562d9f60083ab980a1b6b3133c1cac
[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         current_atcdialog->PopupDialog();
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   callback_code = 0;
58 }
59
60 ATCMenuEntry::~ATCMenuEntry() {
61 }
62
63 static void atcUppercase(string &s) {
64         for(unsigned int i=0; i<s.size(); ++i) {
65                 s[i] = toupper(s[i]);
66         }
67 }
68
69 // ----------------------- Popup Dialog Statics------------------
70 static puDialogBox*             atcDialog;
71 static puFrame*                 atcDialogFrame;
72 static puText*                  atcDialogMessage;
73 static puOneShot*               atcDialogOkButton;
74 static puOneShot*               atcDialogCancelButton;
75 static puButtonBox*             atcDialogCommunicationOptions;
76 // --------------------------------------------------------------
77
78 // ----------------------- Freq Dialog Statics-------------------
79 static const int ATC_MAX_FREQ_DISPLAY = 20;             // Maximum number of frequencies that can be displayed for any one airport
80
81 static puDialogBox*     atcFreqDialog;
82 static puFrame*         atcFreqDialogFrame;
83 static puText*          atcFreqDialogMessage;
84 static puInput*         atcFreqDialogInput;
85 static puOneShot*       atcFreqDialogOkButton;
86 static puOneShot*       atcFreqDialogCancelButton;
87
88 static puDialogBox*     atcFreqDisplay;
89 static puFrame*         atcFreqDisplayFrame;
90 static puText*          atcFreqDisplayMessage;
91 static puOneShot*       atcFreqDisplayOkButton;
92 static puText*          atcFreqDisplayText[ATC_MAX_FREQ_DISPLAY];
93 // --------------------------------------------------------------
94
95 //////////////// Popup callbacks ///////////////////
96 static void ATCDialogOK(puObject *)
97 {
98         switch(atcDialogCommunicationOptions->getValue()) {
99         case 0:
100                 //cout << "Option 0 chosen\n";
101                 fgSetBool("/sim/atc/opt0",true);
102                 break;
103         case 1:
104                 //cout << "Option 1 chosen\n";
105                 fgSetBool("/sim/atc/opt1",true);
106                 break;
107         case 2:
108                 //cout << "Option 2 chosen\n";
109                 fgSetBool("/sim/atc/opt2",true);
110                 break;
111         case 3:
112                 //cout << "Option 2 chosen\n";
113                 fgSetBool("/sim/atc/opt3",true);
114                 break;
115         default:
116                 break;
117         }
118         FG_POP_PUI_DIALOG( atcDialog );
119 }
120
121 static void ATCDialogCancel(puObject *)
122 {
123     FG_POP_PUI_DIALOG( atcDialog );
124 }
125 //////////////////////////////////////////////////
126
127
128 ///////////////// Freq search callbacks ///////////
129 static void FreqDialogCancel(puObject*) {
130         FG_POP_PUI_DIALOG(atcFreqDialog);
131 }
132
133 static void FreqDialogOK(puObject*) {
134         string tmp = atcFreqDialogInput->getStringValue();
135         FG_POP_PUI_DIALOG(atcFreqDialog);
136         current_atcdialog->FreqDisplay(tmp);
137 }
138
139 static void FreqDisplayOK(puObject*) {
140         FG_POP_PUI_DIALOG(atcFreqDisplay);
141 }
142 //////////////////////////////////////////////////
143
144
145 FGATCDialog::FGATCDialog() {
146 }
147
148 FGATCDialog::~FGATCDialog() {
149         if(atcDialog) puDeleteObject(atcDialog);
150         if(atcFreqDialog) puDeleteObject(atcFreqDialog);
151         if(atcFreqDisplay) puDeleteObject(atcFreqDisplay);
152 }
153
154 void FGATCDialog::Init() {
155         // Add ATC-dialog to the command list
156         globals->get_commands()->addCommand("ATC-dialog", do_ATC_dialog);
157         // Add ATC-freq-search to the command list
158         globals->get_commands()->addCommand("ATC-freq-search", do_ATC_freq_search);
159         
160         int w;
161         int h;
162         int x;
163         int y;
164         
165         // Init the freq-search dialog
166         w = 300;
167         h = 150;
168         x = (fgGetInt("/sim/startup/xsize") / 2) - (w / 2);
169         y = 50;
170         char *s;
171         atcFreqDialog = new puDialogBox (x, y);
172         {
173                 atcFreqDialogFrame = new puFrame (0, 0, w, h);
174                 atcFreqDialogMessage = new puText          (40, (h - 30));
175                 atcFreqDialogMessage->setDefaultValue ("Enter airport identifier:");
176                 atcFreqDialogMessage->getDefaultValue (&s);
177                 atcFreqDialogMessage->setLabel(s);
178         
179                 atcFreqDialogInput = new puInput (50, (h - 75), 150, (h - 45));
180                         
181                 atcFreqDialogOkButton     =  new puOneShot         (50, 10, 110, 50);
182                 atcFreqDialogOkButton     ->     setLegend         (gui_msg_OK);
183                 atcFreqDialogOkButton     ->     makeReturnDefault (TRUE);
184                 atcFreqDialogOkButton     ->     setCallback       (FreqDialogOK);
185                         
186                 atcFreqDialogCancelButton =  new puOneShot         (140, 10, 210, 50);
187                 atcFreqDialogCancelButton ->     setLegend         (gui_msg_CANCEL);
188                 atcFreqDialogCancelButton ->     setCallback       (FreqDialogCancel);
189                 
190                 atcFreqDialogInput->acceptInput();
191         }
192         
193         FG_FINALIZE_PUI_DIALOG(atcFreqDialog);
194         
195         // Init the freq-display dialog
196         w = 400;
197         h = 100;
198         x = (fgGetInt("/sim/startup/xsize") / 2) - (w / 2);
199         y = 50;
200         atcFreqDisplay = new puDialogBox (x, y);
201         {
202                 atcFreqDisplayFrame   = new puFrame (0, 0, w, h);
203                 
204                 atcFreqDisplayMessage = new puText          (40, (h - 30));
205                 atcFreqDisplayMessage    -> setDefaultValue ("No freqencies found");
206                 atcFreqDisplayMessage    -> getDefaultValue (&s);
207                 atcFreqDisplayMessage    -> setLabel        (s);
208                 
209                 for(int i=0; i<ATC_MAX_FREQ_DISPLAY; ++i) {
210                         atcFreqDisplayText[i] = new puText(40, h - 65 - (30 * i));
211                         atcFreqDisplayText[i]->setDefaultValue("");
212                         atcFreqDisplayText[i]-> getDefaultValue (&s);
213                         atcFreqDisplayText[i]-> setLabel        (s);
214                         atcFreqDisplayText[i]->hide();
215                 }
216                 
217                 atcFreqDisplayOkButton     =  new puOneShot         (50, 10, 110, 50);
218                 atcFreqDisplayOkButton     ->     setLegend         (gui_msg_OK);
219                 atcFreqDisplayOkButton     ->     makeReturnDefault (TRUE);
220                 atcFreqDisplayOkButton     ->     setCallback       (FreqDisplayOK);
221         }
222         FG_FINALIZE_PUI_DIALOG(atcFreqDisplay);
223         
224         // Init AK's interactive ATC menus
225         w = 500;
226         h = 110;
227         x = (fgGetInt("/sim/startup/xsize") / 2) - (w / 2);
228         //y = (fgGetInt("/sim/startup/ysize") / 2) - (h / 2);
229         y = 50;
230         atcDialog = new puDialogBox (x, y);
231         {
232                 atcDialogFrame = new puFrame (0,0,w,h);
233                 atcDialogMessage = new puText (w / 2, h - 30);
234                 atcDialogMessage -> setLabel( "No transmission available" );
235                 atcDialogMessage -> setLabelPlace(PUPLACE_TOP_CENTERED);
236                 atcDialogCommunicationOptions = new puButtonBox (50, 60, 450, 50, NULL, true);
237                 atcDialogCommunicationOptions -> hide();
238                 atcDialogOkButton     =  new puOneShot         ((w/2)-85, 10, (w/2)-25, 50);
239                 atcDialogOkButton     ->     setLegend         (gui_msg_OK);
240                 atcDialogOkButton     ->     makeReturnDefault (TRUE);
241                 atcDialogOkButton     ->     setCallback       (ATCDialogOK);
242                 
243                 atcDialogCancelButton =  new puOneShot         ((w/2)+25, 10, (w/2)+85, 50);
244                 atcDialogCancelButton ->     setLegend         (gui_msg_CANCEL);
245                 atcDialogCancelButton ->     setCallback       (ATCDialogCancel);
246         }
247         FG_FINALIZE_PUI_DIALOG(atcDialog);
248 }
249
250 // Add an entry
251 void FGATCDialog::add_entry(string station, string transmission, string menutext, atc_type type, int code) {
252
253   ATCMenuEntry a;
254
255   a.stationid = station;
256   a.transmission = transmission;
257   a.menuentry = menutext;
258   a.callback_code = code;
259
260   //atcmentrylist_station[station.c_str()].push_back(a);
261   (available_dialog[type])[station.c_str()].push_back(a);
262
263 }
264
265 void FGATCDialog::remove_entry( const string &station, const string &trans, atc_type type ) {
266   atcmentry_vec_type     atcmlist = (available_dialog[type])[station];
267   atcmentry_vec_iterator current  = atcmlist.begin();
268   atcmentry_vec_iterator last     = atcmlist.end();
269   
270   while(current != last) {
271     if(current->transmission == trans) current = atcmlist.erase(current);
272         else ++current;
273   }
274 }
275
276 void FGATCDialog::remove_entry( const string &station, int code, atc_type type ) {
277   atcmentry_vec_type     atcmlist = (available_dialog[type])[station];
278   atcmentry_vec_iterator current  = atcmlist.begin();
279   atcmentry_vec_iterator last     = atcmlist.end();
280   
281   while(current != last) {
282     if(current->callback_code == code) current = atcmlist.erase(current);
283         else ++current;
284   }
285 }
286
287 // query the database whether the transmission is already registered; 
288 bool FGATCDialog::trans_reg( const string &station, const string &trans, atc_type type ) {
289   //atcmentry_list_type     atcmlist = atcmentrylist_station[station];
290   atcmentry_vec_type     atcmlist = (available_dialog[type])[station];
291   atcmentry_vec_iterator current  = atcmlist.begin();
292   atcmentry_vec_iterator last     = atcmlist.end();
293   
294   for ( ; current != last ; ++current ) {
295     if ( current->transmission == trans ) return true;
296   }
297   return false;
298 }
299
300 // query the database whether the transmission is already registered; 
301 bool FGATCDialog::trans_reg( const string &station, int code, atc_type type ) {
302   //atcmentry_list_type     atcmlist = atcmentrylist_station[station];
303   atcmentry_vec_type     atcmlist = (available_dialog[type])[station];
304   atcmentry_vec_iterator current  = atcmlist.begin();
305   atcmentry_vec_iterator last     = atcmlist.end();
306   
307   for ( ; current != last ; ++current ) {
308     if ( current->callback_code == code ) return true;
309   }
310   return false;
311 }
312
313 // Display the ATC popup dialog box with options relevant to the users current situation.
314 void FGATCDialog::PopupDialog() {
315         
316         static string mentry[10];
317         static string mtrans[10];
318         char   buf[10];
319         TransPar TPar;
320         FGATC* atcptr = globals->get_ATC_mgr()->GetComm1ATCPointer();   // Hardwired to comm1 at the moment
321         
322         int w = 500;
323         int h = 100;
324         if(atcptr) {
325                 if(atcptr->GetType() == ATIS) {
326                         atcDialogCommunicationOptions->hide();
327                         atcDialogMessage -> setLabel( "Tuned to ATIS - no communication possible" );
328                         atcDialogFrame->setSize(w, h);
329                         atcDialogMessage -> setPosition(w / 2, h - 30);
330                 } else {
331                         
332                         atcmentry_vec_type atcmlist = (available_dialog[atcptr->GetType()])[atcptr->get_ident()];
333                         atcmentry_vec_iterator current = atcmlist.begin();
334                         atcmentry_vec_iterator last = atcmlist.end();
335                         
336                         // Set all opt flags to false before displaying box
337                         fgSetBool("/sim/atc/opt0",false);
338                         fgSetBool("/sim/atc/opt1",false);
339                         fgSetBool("/sim/atc/opt2",false);
340                         fgSetBool("/sim/atc/opt3",false);
341                         fgSetBool("/sim/atc/opt4",false);
342                         fgSetBool("/sim/atc/opt5",false);
343                         fgSetBool("/sim/atc/opt6",false);
344                         fgSetBool("/sim/atc/opt7",false);
345                         fgSetBool("/sim/atc/opt8",false);
346                         fgSetBool("/sim/atc/opt9",false);
347                         
348                         int k = atcmlist.size();
349                         h += k * 25;
350                         //cout << "k = " << k << '\n';
351                         
352                         atcDialogFrame->setSize(w, h); 
353                         
354                         if(k) { 
355                                 // loop over all entries in atcmentrylist
356                                 char** optList = new char*[k+1];
357                                 int kk = 0;
358                                 for ( ; current != last ; ++current ) {
359                                         string dum;
360                                         sprintf( buf, "%i", kk+1 );
361                                         buf[1] = '\0';
362                                         dum = buf;
363                                         mentry[kk] = dum + ". " + current->menuentry;
364                                         optList[kk] = new char[strlen(mentry[kk].c_str()) + 1];
365                                         strcpy(optList[kk], mentry[kk].c_str());
366                                         //cout << "optList[" << kk << "] = " << optList[kk] << endl; 
367                                         mtrans[kk] =              current->transmission;
368                                         ++kk;
369                                 } 
370                                 optList[k] = NULL;
371                                 atcDialogCommunicationOptions->newList(optList);
372                                 atcDialogCommunicationOptions->setSize(w-100, h-100);
373                                 atcDialogCommunicationOptions->reveal();
374                                 atcDialogMessage -> setLabel( "ATC Menu" );
375                                 atcDialogMessage -> setPosition(w / 2, h - 30);
376                         } else {
377                                 atcDialogCommunicationOptions->hide();
378                                 atcDialogMessage -> setLabel( "No transmission available" );
379                                 atcDialogMessage -> setPosition(w / 2, h - 30);
380                         }
381                 }
382         } else {
383                 atcDialogCommunicationOptions->hide();
384                 atcDialogMessage -> setLabel( "Not currently tuned to any ATC service" );
385                 atcDialogFrame->setSize(w, h);
386                 atcDialogMessage -> setPosition(w / 2, h - 30);
387         }
388                 
389         FG_PUSH_PUI_DIALOG(atcDialog);
390 }
391
392
393
394 void FGATCDialog::FreqDialog() {
395
396         // Find the ATC stations within a reasonable range (about 40 miles?)
397         //comm_list_type atc_stations;
398         //comm_list_iterator atc_stat_itr;
399         
400         //double lon = fgGetDouble("/position/longitude-deg");
401         //double lat = fgGetDouble("/position/latitude-deg");
402         //double elev = fgGetDouble("/position/altitude-ft");
403         
404         /*
405         // search stations in range
406         int num_stat = current_commlist->FindByPos(lon, lat, elev, 40.0, &atc_stations);
407         if (num_stat != 0) {
408         } else {
409                 // Make up a message saying no things in range
410         }
411         */
412         
413         // TODO - it would be nice to display a drop-down list of airports within the general vicinity of the user
414         //        in addition to the general input box (started above).
415         
416         atcFreqDialogInput->setValue("");
417         atcFreqDialogInput->acceptInput();
418         FG_PUSH_PUI_DIALOG(atcFreqDialog);
419 }
420
421 void FGATCDialog::FreqDisplay(string ident) {
422
423         atcUppercase(ident);
424         
425         string label;
426         char *s;
427         
428         int n = 0;      // Number of ATC frequencies at this airport
429         string freqs[ATC_MAX_FREQ_DISPLAY];
430         char buf[8];
431
432     FGAirport a;
433     if ( dclFindAirportID( ident, &a ) ) {
434                 comm_list_type stations;
435                 int found = current_commlist->FindByPos(a.longitude, a.latitude, a.elevation, 20.0, &stations);
436                 if(found) {
437                         ostringstream ostr;
438                         comm_list_iterator itr = stations.begin();
439                         while(itr != stations.end()) {
440                                 if((*itr).ident == ident) {
441                                         if((*itr).type != INVALID) {
442                                                 ostr << (*itr).type;
443                                                 freqs[n] = ostr.str();
444                                                 freqs[n].append("     -     ");
445                                                 sprintf(buf, "%.2f", ((*itr).freq / 100.0));    // Convert from KHz to MHz
446                                                 // Hack alert!
447                                                 if(buf[5] == '3') buf[5] = '2';
448                                                 if(buf[5] == '8') buf[5] = '7';
449                                                 freqs[n] += buf;
450                                                 ostr.seekp(0);
451                                                 n++;
452                                         }
453                                 }
454                                 ++itr;
455                         }
456                 }
457                 if(n == 0) {
458                         label = "No frequencies found for airport ";
459                         label += ident;
460                 } else {
461                         label = "Frequencies for airport ";
462                         label += ident;
463                         label += ":";
464                 }
465     } else {
466                 label = "Airport ";
467                 label += ident;
468                 label += " not found in database.";
469         }
470
471         int hsize = 105 + (n * 30);
472         
473         atcFreqDisplayFrame->setSize(400, hsize);
474         
475         atcFreqDisplayMessage -> setPosition (40, (hsize - 30));
476         atcFreqDisplayMessage -> setValue    (label.c_str());
477         atcFreqDisplayMessage -> getValue    (&s);
478         atcFreqDisplayMessage -> setLabel    (s);
479         
480         for(int i=0; i<n; ++i) {
481                 atcFreqDisplayText[i] -> setPosition(40, hsize - 65 - (30 * i));
482                 atcFreqDisplayText[i] -> setValue(freqs[i].c_str());
483                 atcFreqDisplayText[i] -> getValue (&s);
484                 atcFreqDisplayText[i] -> setLabel (s);
485                 atcFreqDisplayText[i] -> reveal();
486         }
487         for(int j=n; j<ATC_MAX_FREQ_DISPLAY; ++j) {
488                 atcFreqDisplayText[j] -> hide();
489         }
490         
491         FG_PUSH_PUI_DIALOG(atcFreqDisplay);
492         
493 }
494