// ATCDialog.cxx - Functions and classes to handle the pop-up ATC dialog // // Written by Alexander Kappes and David Luff, started February 2003. // // Copyright (C) 2003 Alexander Kappes and David Luff // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include
#include #include "ATCDialog.hxx" #include "ATC.hxx" #include "ATCmgr.hxx" #include "commlist.hxx" #include "ATCutils.hxx" #include #include SG_USING_STD(ostringstream); static void atcUppercase(string &s) { for(unsigned int i=0; iget_ATC_mgr()->doPopupDialog(); return(true); } static bool do_ATC_freq_search(const SGPropertyNode* arg) { current_atcdialog->FreqDialog(); return(true); } ATCMenuEntry::ATCMenuEntry() { stationid = ""; stationfr = 0; transmission = ""; menuentry = ""; } ATCMenuEntry::~ATCMenuEntry() { } static char* t0 = "No communication currently available"; //static char* t1 = "Request departure clearance"; //static char* t2 = "Report Runway vacated"; static char** towerOptions = new char*[2]; // ----------------------- DCL ------------------------------------------ // For the ATC dialog - copied from the Autopilot new heading dialog code! static puDialogBox* atcDialog; static puFrame* atcDialogFrame; static puText* atcDialogMessage; //static puInput* atcDialogInput; static puOneShot* atcDialogOkButton; static puOneShot* atcDialogCancelButton; static puButtonBox* atcDialogCommunicationOptions; // ---------------------------------------------------------------------- ////////////////////////////////////////////////////// // // STUFF FOR THE FREQUENCY SEARCH DIALOG // ////////////////////////////////////////////////////// static const int ATC_MAX_FREQ_DISPLAY = 20; // Maximum number of frequencies that can be displayed for any one airport static puDialogBox* atcFreqDialog; static puFrame* atcFreqDialogFrame; static puText* atcFreqDialogMessage; static puInput* atcFreqDialogInput; static puOneShot* atcFreqDialogOkButton; static puOneShot* atcFreqDialogCancelButton; static puDialogBox* atcFreqDisplay; static puFrame* atcFreqDisplayFrame; static puText* atcFreqDisplayMessage; static puOneShot* atcFreqDisplayOkButton; static puText* atcFreqDisplayText[ATC_MAX_FREQ_DISPLAY]; static void FreqDialogCancel(puObject*) { FG_POP_PUI_DIALOG(atcFreqDialog); } static void FreqDialogOK(puObject*) { string tmp = atcFreqDialogInput->getStringValue(); FG_POP_PUI_DIALOG(atcFreqDialog); current_atcdialog->FreqDisplay(tmp); } static void FreqDisplayOK(puObject*) { FG_POP_PUI_DIALOG(atcFreqDisplay); } ////////////// end freq search statics /////////////// // ------------------------ AK ------------------------------------------ static puDialogBox *ATCMenuBox = 0; static puFrame *ATCMenuFrame = 0; static puText *ATCMenuBoxMessage = 0; static puButtonBox *ATCOptionsList = 0; // ---------------------------------------------------------------------- // AK static void AKATCDialogOK(puObject *) { switch(ATCOptionsList->getValue()) { case 0: //cout << "Option 0 chosen\n"; fgSetBool("/sim/atc/opt0",true); break; case 1: //cout << "Option 1 chosen\n"; fgSetBool("/sim/atc/opt1",true); break; case 2: //cout << "Option 2 chosen\n"; fgSetBool("/sim/atc/opt2",true); break; case 3: //cout << "Option 2 chosen\n"; fgSetBool("/sim/atc/opt3",true); break; default: break; } FG_POP_PUI_DIALOG( ATCMenuBox ); } // AK static void AKATCDialogCancel(puObject *) { FG_POP_PUI_DIALOG( ATCMenuBox ); } // DCL static void ATCDialogCancel(puObject *) { //ATCDialogInput->rejectInput(); FG_POP_PUI_DIALOG( atcDialog ); } // DCL static void ATCDialogOK (puObject *me) { // Note that currently the dialog is hardwired to comm1 only here. switch(globals->get_ATC_mgr()->GetComm1ATCType()) { case INVALID: break; case ATIS: break; case TOWER: { /* FGTower* twr = (FGTower*)globals->get_ATC_mgr()->GetComm1ATCPointer(); switch(atcDialogCommunicationOptions->getValue()) { case 0: //cout << "Option 0 chosen\n"; twr->RequestLandingClearance("charlie foxtrot sierra"); break; case 1: //cout << "Option 1 chosen\n"; twr->RequestDepartureClearance("charlie foxtrot sierra"); break; case 2: //cout << "Option 2 chosen\n"; twr->ReportRunwayVacated("charlie foxtrot sierra"); break; default: break; } */ break; } case GROUND: break; case APPROACH: break; default: break; } ATCDialogCancel(me); //if(error) mkDialog(s.c_str()); } // DCL static void ATCDialog(puObject *cb) { FG_PUSH_PUI_DIALOG(atcDialog); } // DCL void ATCDialogInit() { char defaultATCLabel[] = "Enter desired option to communicate with ATC:"; char *s; // Option lists hardwired per ATC type towerOptions[0] = new char[strlen(t0)+1]; strcpy(towerOptions[0], t0); //towerOptions[1] = new char[strlen(t1)+1]; //strcpy(towerOptions[1], t1); //towerOptions[2] = new char[strlen(t2)+1]; //strcpy(towerOptions[2], t2); towerOptions[1] = NULL; atcDialog = new puDialogBox (150, 50); { atcDialogFrame = new puFrame (0, 0, 500, 250); atcDialogMessage = new puText (250, 220); atcDialogMessage -> setDefaultValue (defaultATCLabel); atcDialogMessage -> getDefaultValue (&s); atcDialogMessage -> setLabel (s); atcDialogMessage -> setLabelPlace (PUPLACE_TOP_CENTERED); atcDialogCommunicationOptions = new puButtonBox (50, 50, 450, 210, NULL, true); atcDialogOkButton = new puOneShot (50, 10, 110, 50); atcDialogOkButton -> setLegend (gui_msg_OK); atcDialogOkButton -> makeReturnDefault (TRUE); atcDialogOkButton -> setCallback (ATCDialogOK); atcDialogCancelButton = new puOneShot (140, 10, 210, 50); atcDialogCancelButton -> setLegend (gui_msg_CANCEL); atcDialogCancelButton -> setCallback (ATCDialogCancel); } FG_FINALIZE_PUI_DIALOG(atcDialog); // Add ATC-dialog to the command list globals->get_commands()->addCommand("ATC-dialog", do_ATC_dialog); } /////////////////////////////////////////////////////////////////////// // // ATCDoDialog is in a state of flux at the moment // Stations other than approach are handled by DCL's simple code // Approach is handled by AK's fancy dynamic-list code // Hopefully all interactive stations should go to AK's code eventually // /////////////////////////////////////////////////////////////////////// void ATCDoDialog(atc_type type) { switch(type) { case INVALID: atcDialogCommunicationOptions->newList(NULL); atcDialogMessage->setLabel("Not tuned in to any ATC service."); break; case ATIS: atcDialogCommunicationOptions->newList(NULL); atcDialogMessage->setLabel("Tuned in to ATIS: no communication possible."); break; case TOWER: atcDialogCommunicationOptions->newList(towerOptions); atcDialogMessage->setLabel("Tuned in to Tower - select communication to transmit:"); break; case GROUND: atcDialogCommunicationOptions->newList(NULL); atcDialogMessage->setLabel("Tuned in to Ground - select communication to transmit:"); break; case APPROACH: current_atcdialog->DoDialog(); break; default: atcDialogCommunicationOptions->newList(NULL); atcDialogMessage->setLabel("Tuned in to unknown ATC service - enter transmission:"); break; } // Third - display the dialog without pausing sim. if(type != APPROACH) { ATCDialog(NULL); } } FGATCDialog::FGATCDialog() { } FGATCDialog::~FGATCDialog() { if(atcFreqDialog) puDeleteObject(atcFreqDialog); if(atcFreqDisplay) puDeleteObject(atcFreqDisplay); if(ATCMenuBox) puDeleteObject(ATCMenuBox); } void FGATCDialog::Init() { // Add ATC-freq-search to the command list globals->get_commands()->addCommand("ATC-freq-search", do_ATC_freq_search); int w; int h; int x; int y; // Init the freq-search dialog w = 300; h = 150; x = (fgGetInt("/sim/startup/xsize") / 2) - (w / 2); y = 50; char *s; atcFreqDialog = new puDialogBox (x, y); { atcFreqDialogFrame = new puFrame (0, 0, w, h); atcFreqDialogMessage = new puText (40, (h - 30)); atcFreqDialogMessage->setDefaultValue ("Enter airport identifier:"); atcFreqDialogMessage->getDefaultValue (&s); atcFreqDialogMessage->setLabel(s); atcFreqDialogInput = new puInput (50, (h - 75), 150, (h - 45)); atcFreqDialogOkButton = new puOneShot (50, 10, 110, 50); atcFreqDialogOkButton -> setLegend (gui_msg_OK); atcFreqDialogOkButton -> makeReturnDefault (TRUE); atcFreqDialogOkButton -> setCallback (FreqDialogOK); atcFreqDialogCancelButton = new puOneShot (140, 10, 210, 50); atcFreqDialogCancelButton -> setLegend (gui_msg_CANCEL); atcFreqDialogCancelButton -> setCallback (FreqDialogCancel); atcFreqDialogInput->acceptInput(); } FG_FINALIZE_PUI_DIALOG(atcFreqDialog); // Init the freq-display dialog w = 400; h = 100; x = (fgGetInt("/sim/startup/xsize") / 2) - (w / 2); y = 50; atcFreqDisplay = new puDialogBox (x, y); { atcFreqDisplayFrame = new puFrame (0, 0, w, h); atcFreqDisplayMessage = new puText (40, (h - 30)); atcFreqDisplayMessage -> setDefaultValue ("No freqencies found"); atcFreqDisplayMessage -> getDefaultValue (&s); atcFreqDisplayMessage -> setLabel (s); for(int i=0; isetDefaultValue(""); atcFreqDisplayText[i]-> getDefaultValue (&s); atcFreqDisplayText[i]-> setLabel (s); atcFreqDisplayText[i]->hide(); } atcFreqDisplayOkButton = new puOneShot (50, 10, 110, 50); atcFreqDisplayOkButton -> setLegend (gui_msg_OK); atcFreqDisplayOkButton -> makeReturnDefault (TRUE); atcFreqDisplayOkButton -> setCallback (FreqDisplayOK); } FG_FINALIZE_PUI_DIALOG(atcFreqDisplay); // Init AK's interactive ATC menus w = 500; h = 110; x = (fgGetInt("/sim/startup/xsize") / 2) - (w / 2); //y = (fgGetInt("/sim/startup/ysize") / 2) - (h / 2); y = 50; ATCMenuBox = new puDialogBox (x, y); { ATCMenuFrame = new puFrame (0,0,w,h); ATCMenuBoxMessage = new puText (w / 2, h - 30); ATCMenuBoxMessage -> setLabel( "No transmission available" ); ATCMenuBoxMessage -> setLabelPlace(PUPLACE_TOP_CENTERED); ATCOptionsList = new puButtonBox (50, 60, 450, 50, NULL, true); ATCOptionsList -> hide(); atcDialogOkButton = new puOneShot ((w/2)-85, 10, (w/2)-25, 50); atcDialogOkButton -> setLegend (gui_msg_OK); atcDialogOkButton -> makeReturnDefault (TRUE); atcDialogOkButton -> setCallback (AKATCDialogOK); atcDialogCancelButton = new puOneShot ((w/2)+25, 10, (w/2)+85, 50); atcDialogCancelButton -> setLegend (gui_msg_CANCEL); atcDialogCancelButton -> setCallback (AKATCDialogCancel); } FG_FINALIZE_PUI_DIALOG(ATCMenuBox); } // AK // Add an entry void FGATCDialog::add_entry(string station, string transmission, string menutext ) { ATCMenuEntry a; a.stationid = station; a.transmission = transmission; a.menuentry = menutext; atcmentrylist_station[station.c_str()].push_back(a); } // AK // query the database whether the transmission is already registered; bool FGATCDialog::trans_reg( const string &station, const string &trans ) { atcmentry_list_type atcmlist = atcmentrylist_station[station]; atcmentry_list_iterator current = atcmlist.begin(); atcmentry_list_iterator last = atcmlist.end(); for ( ; current != last ; ++current ) { if ( current->transmission == trans ) return true; } return false; } // AK // =================================================== // === Update ATC menue and look for keys pressed === // =================================================== void FGATCDialog::DoDialog() { static string mentry[10]; static string mtrans[10]; char buf[10]; TransPar TPar; FGATC* atcptr = globals->get_ATC_mgr()->GetComm1ATCPointer(); // Hardwired to comm1 at the moment if(atcptr != NULL) { atcmentry_list_type atcmlist = atcmentrylist_station[atcptr->get_ident()]; //atcmentry_list_type atcmlist = atcmentrylist_station["EGNX"]; atcmentry_list_iterator current = atcmlist.begin(); atcmentry_list_iterator last = atcmlist.end(); // Set all opt flags to false before displaying box fgSetBool("/sim/atc/opt0",false); fgSetBool("/sim/atc/opt1",false); fgSetBool("/sim/atc/opt2",false); fgSetBool("/sim/atc/opt3",false); fgSetBool("/sim/atc/opt4",false); fgSetBool("/sim/atc/opt5",false); fgSetBool("/sim/atc/opt6",false); fgSetBool("/sim/atc/opt7",false); fgSetBool("/sim/atc/opt8",false); fgSetBool("/sim/atc/opt9",false); int w = 500; int k = atcmlist.size(); int h = 110 + k * 25; //cout << "k = " << k << '\n'; ATCMenuFrame->setSize(w, h); if(k) { // loop over all entries in atcmentrylist char** optList = new char*[k+1]; int kk = 0; for ( ; current != last ; ++current ) { string dum; sprintf( buf, "%i", kk+1 ); buf[1] = '\0'; dum = buf; mentry[kk] = dum + ". " + current->menuentry; optList[kk] = new char[strlen(mentry[kk].c_str()) + 1]; strcpy(optList[kk], mentry[kk].c_str()); //cout << "optList[" << kk << "] = " << optList[kk] << endl; mtrans[kk] = current->transmission; ++kk; } optList[k] = NULL; ATCOptionsList->newList(optList); ATCOptionsList->setSize(w-100, h-100); ATCOptionsList->reveal(); ATCMenuBoxMessage -> setLabel( "ATC Menu" ); ATCMenuBoxMessage -> setPosition(w / 2, h - 30); } else { ATCOptionsList->hide(); ATCMenuBoxMessage -> setLabel( "No transmission available" ); ATCMenuBoxMessage -> setPosition(w / 2, h - 20); } FG_PUSH_PUI_DIALOG( ATCMenuBox ); /* if ( atckey != -1 && TransDisplayed && mtrans[atckey-1].c_str() != "" ) { cout << mtrans[atckey-1].c_str() << endl; TPar = current_transmissionlist->extract_transpar( mtrans[atckey-1].c_str() ); current_atcmentrylist->reset = true; current_transparlist->add_entry( TPar ); // transpar_list_type test = current_transparlist; // transpar_list_iterator current = test.begin(); //for ( ; current != test.end(); ++current ) { // current->tpar.intention; //} } if ( current_atcmentrylist->freq != (int)(comm1_freq*100.0 + 0.5) ) { current_atcmentrylist->reset = true; } // reset (delete) ATCmenue list if reset is true if ( current_atcmentrylist->reset == true ) { delete ( current_atcmentrylist ); current_atcmentrylist = new FGatcmentryList; current_atcmentrylist->init( (int)(comm1_freq*100.0 + 0.5) ); if ( TransDisplayed ) { FG_POP_PUI_DIALOG( ATCMenuBox ); TransDisplayed = false; } } */ } } void FGATCDialog::FreqDialog() { // Find the ATC stations within a reasonable range (about 40 miles?) //comm_list_type atc_stations; //comm_list_iterator atc_stat_itr; //double lon = fgGetDouble("/position/longitude-deg"); //double lat = fgGetDouble("/position/latitude-deg"); //double elev = fgGetDouble("/position/altitude-ft"); /* // search stations in range int num_stat = current_commlist->FindByPos(lon, lat, elev, 40.0, &atc_stations); if (num_stat != 0) { } else { // Make up a message saying no things in range } */ // TODO - it would be nice to display a drop-down list of airports within the general vicinity of the user // in addition to the general input box (started above). atcFreqDialogInput->setValue(""); atcFreqDialogInput->acceptInput(); FG_PUSH_PUI_DIALOG(atcFreqDialog); } void FGATCDialog::FreqDisplay(string ident) { atcUppercase(ident); string label; char *s; int n = 0; // Number of ATC frequencies at this airport string freqs[ATC_MAX_FREQ_DISPLAY]; char buf[8]; FGAirport a; if ( dclFindAirportID( ident, &a ) ) { comm_list_type stations; int found = current_commlist->FindByPos(a.longitude, a.latitude, a.elevation, 20.0, &stations); if(found) { ostringstream ostr; comm_list_iterator itr = stations.begin(); while(itr != stations.end()) { if((*itr).ident == ident) { if((*itr).type != INVALID) { ostr << (*itr).type; freqs[n] = ostr.str(); freqs[n].append(" - "); sprintf(buf, "%.2f", ((*itr).freq / 100.0)); // Convert from KHz to MHz // Hack alert! if(buf[5] == '3') buf[5] = '2'; if(buf[5] == '8') buf[5] = '7'; freqs[n] += buf; ostr.seekp(0); n++; } } ++itr; } } if(n == 0) { label = "No frequencies found for airport "; label += ident; } else { label = "Frequencies for airport "; label += ident; label += ":"; } } else { label = "Airport "; label += ident; label += " not found in database."; } int hsize = 105 + (n * 30); atcFreqDisplayFrame->setSize(400, hsize); atcFreqDisplayMessage -> setPosition (40, (hsize - 30)); atcFreqDisplayMessage -> setValue (label.c_str()); atcFreqDisplayMessage -> getValue (&s); atcFreqDisplayMessage -> setLabel (s); for(int i=0; i setPosition(40, hsize - 65 - (30 * i)); atcFreqDisplayText[i] -> setValue(freqs[i].c_str()); atcFreqDisplayText[i] -> getValue (&s); atcFreqDisplayText[i] -> setLabel (s); atcFreqDisplayText[i] -> reveal(); } for(int j=n; j hide(); } FG_PUSH_PUI_DIALOG(atcFreqDisplay); }