1 // ATCDialog.cxx - Functions and classes to handle the pop-up ATC dialog
3 // Written by Alexander Kappes and David Luff, started February 2003.
5 // Copyright (C) 2003 Alexander Kappes and David Luff
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.
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.
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.
21 #include <simgear/compiler.h>
23 #include <simgear/structure/commands.hxx>
25 #include <Main/globals.hxx>
28 #include "ATCDialog.hxx"
31 #include "commlist.hxx"
32 #include "ATCutils.hxx"
33 #include <Airports/simple.hxx>
37 SG_USING_STD(ostringstream);
39 FGATCDialog *current_atcdialog;
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();
47 static bool do_ATC_freq_search(const SGPropertyNode* arg) {
48 current_atcdialog->FreqDialog();
52 ATCMenuEntry::ATCMenuEntry() {
60 ATCMenuEntry::~ATCMenuEntry() {
63 static void atcUppercase(string &s) {
64 for(unsigned int i=0; i<s.size(); ++i) {
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 // --------------------------------------------------------------
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
81 static puDialogBox* atcFreqDialog;
82 static puFrame* atcFreqDialogFrame;
83 static puText* atcFreqDialogMessage;
84 static puInput* atcFreqDialogInput;
85 static puOneShot* atcFreqDialogOkButton;
86 static puOneShot* atcFreqDialogCancelButton;
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 // --------------------------------------------------------------
95 //////////////// Popup callbacks ///////////////////
96 static void ATCDialogOK(puObject *)
98 switch(atcDialogCommunicationOptions->getValue()) {
100 //cout << "Option 0 chosen\n";
101 fgSetBool("/sim/atc/opt0",true);
104 //cout << "Option 1 chosen\n";
105 fgSetBool("/sim/atc/opt1",true);
108 //cout << "Option 2 chosen\n";
109 fgSetBool("/sim/atc/opt2",true);
112 //cout << "Option 2 chosen\n";
113 fgSetBool("/sim/atc/opt3",true);
118 FG_POP_PUI_DIALOG( atcDialog );
121 static void ATCDialogCancel(puObject *)
123 FG_POP_PUI_DIALOG( atcDialog );
125 //////////////////////////////////////////////////
128 ///////////////// Freq search callbacks ///////////
129 static void FreqDialogCancel(puObject*) {
130 FG_POP_PUI_DIALOG(atcFreqDialog);
133 static void FreqDialogOK(puObject*) {
134 string tmp = atcFreqDialogInput->getStringValue();
135 FG_POP_PUI_DIALOG(atcFreqDialog);
136 current_atcdialog->FreqDisplay(tmp);
139 static void FreqDisplayOK(puObject*) {
140 FG_POP_PUI_DIALOG(atcFreqDisplay);
142 //////////////////////////////////////////////////
145 FGATCDialog::FGATCDialog() {
148 FGATCDialog::~FGATCDialog() {
149 if(atcDialog) puDeleteObject(atcDialog);
150 if(atcFreqDialog) puDeleteObject(atcFreqDialog);
151 if(atcFreqDisplay) puDeleteObject(atcFreqDisplay);
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);
165 // Init the freq-search dialog
168 x = (fgGetInt("/sim/startup/xsize") / 2) - (w / 2);
171 atcFreqDialog = new puDialogBox (x, y);
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);
179 atcFreqDialogInput = new puInput (50, (h - 75), 150, (h - 45));
181 atcFreqDialogOkButton = new puOneShot (50, 10, 110, 50);
182 atcFreqDialogOkButton -> setLegend (gui_msg_OK);
183 atcFreqDialogOkButton -> makeReturnDefault (TRUE);
184 atcFreqDialogOkButton -> setCallback (FreqDialogOK);
186 atcFreqDialogCancelButton = new puOneShot (140, 10, 210, 50);
187 atcFreqDialogCancelButton -> setLegend (gui_msg_CANCEL);
188 atcFreqDialogCancelButton -> setCallback (FreqDialogCancel);
190 atcFreqDialogInput->acceptInput();
193 FG_FINALIZE_PUI_DIALOG(atcFreqDialog);
195 // Init the freq-display dialog
198 x = (fgGetInt("/sim/startup/xsize") / 2) - (w / 2);
200 atcFreqDisplay = new puDialogBox (x, y);
202 atcFreqDisplayFrame = new puFrame (0, 0, w, h);
204 atcFreqDisplayMessage = new puText (40, (h - 30));
205 atcFreqDisplayMessage -> setDefaultValue ("No freqencies found");
206 atcFreqDisplayMessage -> getDefaultValue (&s);
207 atcFreqDisplayMessage -> setLabel (s);
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();
217 atcFreqDisplayOkButton = new puOneShot (50, 10, 110, 50);
218 atcFreqDisplayOkButton -> setLegend (gui_msg_OK);
219 atcFreqDisplayOkButton -> makeReturnDefault (TRUE);
220 atcFreqDisplayOkButton -> setCallback (FreqDisplayOK);
222 FG_FINALIZE_PUI_DIALOG(atcFreqDisplay);
224 // Init AK's interactive ATC menus
227 x = (fgGetInt("/sim/startup/xsize") / 2) - (w / 2);
228 //y = (fgGetInt("/sim/startup/ysize") / 2) - (h / 2);
230 atcDialog = new puDialogBox (x, y);
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);
243 atcDialogCancelButton = new puOneShot ((w/2)+25, 10, (w/2)+85, 50);
244 atcDialogCancelButton -> setLegend (gui_msg_CANCEL);
245 atcDialogCancelButton -> setCallback (ATCDialogCancel);
247 FG_FINALIZE_PUI_DIALOG(atcDialog);
251 void FGATCDialog::add_entry(string station, string transmission, string menutext, atc_type type, int code) {
255 a.stationid = station;
256 a.transmission = transmission;
257 a.menuentry = menutext;
258 a.callback_code = code;
260 //atcmentrylist_station[station.c_str()].push_back(a);
261 (available_dialog[type])[station.c_str()].push_back(a);
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();
270 while(current != last) {
271 if(current->transmission == trans) current = atcmlist.erase(current);
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();
281 while(current != last) {
282 if(current->callback_code == code) current = atcmlist.erase(current);
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();
294 for ( ; current != last ; ++current ) {
295 if ( current->transmission == trans ) return true;
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();
307 for ( ; current != last ; ++current ) {
308 if ( current->callback_code == code ) return true;
313 // Display the ATC popup dialog box with options relevant to the users current situation.
314 void FGATCDialog::PopupDialog() {
316 static string mentry[10];
317 static string mtrans[10];
320 FGATC* atcptr = globals->get_ATC_mgr()->GetComm1ATCPointer(); // Hardwired to comm1 at the moment
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);
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();
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);
348 int k = atcmlist.size();
350 //cout << "k = " << k << '\n';
352 atcDialogFrame->setSize(w, h);
355 // loop over all entries in atcmentrylist
356 char** optList = new char*[k+1];
358 for ( ; current != last ; ++current ) {
360 sprintf( buf, "%i", kk+1 );
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;
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);
377 atcDialogCommunicationOptions->hide();
378 atcDialogMessage -> setLabel( "No transmission available" );
379 atcDialogMessage -> setPosition(w / 2, h - 30);
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);
389 FG_PUSH_PUI_DIALOG(atcDialog);
394 void FGATCDialog::FreqDialog() {
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;
400 //double lon = fgGetDouble("/position/longitude-deg");
401 //double lat = fgGetDouble("/position/latitude-deg");
402 //double elev = fgGetDouble("/position/altitude-ft");
405 // search stations in range
406 int num_stat = current_commlist->FindByPos(lon, lat, elev, 40.0, &atc_stations);
409 // Make up a message saying no things in range
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).
416 atcFreqDialogInput->setValue("");
417 atcFreqDialogInput->acceptInput();
418 FG_PUSH_PUI_DIALOG(atcFreqDialog);
421 void FGATCDialog::FreqDisplay(string ident) {
428 int n = 0; // Number of ATC frequencies at this airport
429 string freqs[ATC_MAX_FREQ_DISPLAY];
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);
438 comm_list_iterator itr = stations.begin();
439 while(itr != stations.end()) {
440 if((*itr).ident == ident) {
441 if((*itr).type != INVALID) {
443 freqs[n] = ostr.str();
444 freqs[n].append(" - ");
445 sprintf(buf, "%.2f", ((*itr).freq / 100.0)); // Convert from KHz to MHz
447 if(buf[5] == '3') buf[5] = '2';
448 if(buf[5] == '8') buf[5] = '7';
458 label = "No frequencies found for airport ";
461 label = "Frequencies for airport ";
468 label += " not found in database.";
471 int hsize = 105 + (n * 30);
473 atcFreqDisplayFrame->setSize(400, hsize);
475 atcFreqDisplayMessage -> setPosition (40, (hsize - 30));
476 atcFreqDisplayMessage -> setValue (label.c_str());
477 atcFreqDisplayMessage -> getValue (&s);
478 atcFreqDisplayMessage -> setLabel (s);
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();
487 for(int j=n; j<ATC_MAX_FREQ_DISPLAY; ++j) {
488 atcFreqDisplayText[j] -> hide();
491 FG_PUSH_PUI_DIALOG(atcFreqDisplay);