// kln89_page_*.[ch]xx - this file is one of the "pages" that // are used in the KLN89 GPS unit simulation. // // Written by David Luff, started 2005. // // Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk // // 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "kln89_page_int.hxx" #include "Navaids/fix.hxx" #include "Navaids/navrecord.hxx" KLN89IntPage::KLN89IntPage(KLN89* parent) : KLN89Page(parent) { _nSubPages = 2; _subPage = 0; _name = "INT"; _int_id = "PORTE"; _last_int_id = ""; _fp = NULL; _nearestVor = NULL; _refNav = NULL; } KLN89IntPage::~KLN89IntPage() { } void KLN89IntPage::Update(double dt) { bool actPage = (_kln89->_activePage->GetName() == "ACT" ? true : false); bool multi; // Not set by FindFirst... bool exact = false; if(_int_id.size() == 5) exact = true; if(_fp == NULL) { _fp = _kln89->FindFirstIntById(_int_id, multi, exact); } else if(_fp->get_ident() != _int_id) { _fp = _kln89->FindFirstIntById(_int_id, multi, exact); } if(_fp) { _int_id = _fp->get_ident(); if(_kln89->GetActiveWaypoint()) { if(_int_id == _kln89->GetActiveWaypoint()->id) { if(!(_kln89->_waypointAlert && _kln89->_blink)) { // Active waypoint arrow _kln89->DrawSpecialChar(4, 2, 0, 3); } } } if(_int_id != _last_int_id) { _nearestVor = _kln89->FindClosestVor(_fp->get_lat() * SG_DEGREES_TO_RADIANS, _fp->get_lon() * SG_DEGREES_TO_RADIANS); if(_nearestVor) { _nvRadial = _kln89->GetMagHeadingFromTo(_nearestVor->get_lat() * SG_DEGREES_TO_RADIANS, _nearestVor->get_lon() * SG_DEGREES_TO_RADIANS, _fp->get_lat() * SG_DEGREES_TO_RADIANS, _fp->get_lon() * SG_DEGREES_TO_RADIANS); _nvDist = _kln89->GetGreatCircleDistance(_nearestVor->get_lat() * SG_DEGREES_TO_RADIANS, _nearestVor->get_lon() * SG_DEGREES_TO_RADIANS, _fp->get_lat() * SG_DEGREES_TO_RADIANS, _fp->get_lon() * SG_DEGREES_TO_RADIANS); _refNav = _nearestVor; // TODO - check that this *always* holds - eg. when changing INT id after explicitly setting ref nav // but with no loss of focus. } else { _refNav = NULL; } _last_int_id = _int_id; } if(_kln89->_mode != KLN89_MODE_CRSR) { if(!_entInvert) { if(!actPage) { _kln89->DrawText(_fp->get_ident(), 2, 1, 3); } else { // If it's the ACT page, The ID is shifted slightly right to make space for the waypoint index. _kln89->DrawText(_fp->get_ident(), 2, 4, 3); char buf[3]; int n = snprintf(buf, 3, "%i", _kln89->GetActiveWaypointIndex() + 1); _kln89->DrawText((string)buf, 2, 3 - n, 3); // We also draw an I to differentiate INT from USR when it's the ACT page _kln89->DrawText("I", 2, 11, 3); } } else { if(!_kln89->_blink) { _kln89->DrawText(_fp->get_ident(), 2, 1, 3, false, 99); _kln89->DrawEnt(); } } } if(_subPage == 0) { _kln89->DrawLatitude(_fp->get_lat(), 2, 3, 2); _kln89->DrawLongitude(_fp->get_lon(), 2, 3, 1); _kln89->DrawDirDistField(_fp->get_lat() * SG_DEGREES_TO_RADIANS, _fp->get_lon() * SG_DEGREES_TO_RADIANS, 2, 0, 0, _to_flag, (_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 6 ? true : false)); } else { _kln89->DrawText("Ref:", 2, 1, 2); _kln89->DrawText("Rad:", 2, 1, 1); _kln89->DrawText("Dis:", 2, 1, 0); if(_refNav) { _kln89->DrawText(_refNav->get_ident(), 2, 9, 2); // TODO - flash and allow to change if under cursor //_kln89->DrawHeading(_nvRadial, 2, 11, 1); //_kln89->DrawDist(_nvDist, 2, 11, 0); // Currently our draw heading and draw dist functions don't do as many decimal points as we want here, // so draw it ourselves! // Heading char buf[10]; snprintf(buf, 6, "%.1f", _nvRadial); string s = buf; _kln89->DrawText(s, 2, 13 - s.size(), 1); _kln89->DrawSpecialChar(0, 2, 13, 1); // Degrees symbol // Dist double d = _nvDist; d *= (_kln89->_distUnits == GPS_DIST_UNITS_NM ? 1.0 : SG_NM_TO_METER * 0.001); snprintf(buf, 9, "%.1f", d); s = buf; s += (_kln89->_distUnits == GPS_DIST_UNITS_NM ? "nm" : "Km"); _kln89->DrawText(s, 2, 14 - s.size(), 0); } } } else { // TODO - when we leave the page with invalid id and return it should // revert to showing the last valid id. Same for vor/ndb/probably apt etc. if(_kln89->_mode != KLN89_MODE_CRSR) _kln89->DrawText(_int_id, 2, 1, 3); if(_subPage == 0) { _kln89->DrawText("- -- --.--'", 2, 3, 2); _kln89->DrawText("---- --.--'", 2, 3, 1); _kln89->DrawSpecialChar(0, 2, 7, 2); _kln89->DrawSpecialChar(0, 2, 7, 1); _kln89->DrawText(">--- ----", 2, 0, 0); _kln89->DrawSpecialChar(0, 2, 4, 0); _kln89->DrawText(_to_flag ? "To" : "Fr", 2, 5, 0); _kln89->DrawText(_kln89->_distUnits == GPS_DIST_UNITS_NM ? "nm" : "km", 2, 12, 0); } } if(_kln89->_mode == KLN89_MODE_CRSR) { if(_uLinePos > 0 && _uLinePos < 6) { // TODO - blink as well _kln89->Underline(2, _uLinePos, 3, 1); } for(unsigned int i = 0; i < _int_id.size(); ++i) { if(_uLinePos != (i + 1)) { _kln89->DrawChar(_int_id[i], 2, i + 1, 3); } else { if(!_kln89->_blink) _kln89->DrawChar(_int_id[i], 2, i + 1, 3); } } } // TODO - fix this duplication - use _id instead of _apt_id, _vor_id, _ndb_id, _int_id etc! _id = _int_id; KLN89Page::Update(dt); } void KLN89IntPage::SetId(const string& s) { _last_int_id = _int_id; _save_int_id = _int_id; _int_id = s; _fp = NULL; } void KLN89IntPage::CrsrPressed() { if(_kln89->_mode == KLN89_MODE_DISP) return; if(_kln89->_obsMode) { _uLinePos = 0; } else { _uLinePos = 1; } if(_subPage == 0) { _maxULinePos = 6; } else { _maxULinePos = 6; } } void KLN89IntPage::ClrPressed() { if(_subPage == 0 && _uLinePos == 6) { _to_flag = !_to_flag; } } void KLN89IntPage::EntPressed() { if(_entInvert) { _entInvert = false; _last_int_id = _int_id; _int_id = _save_int_id; } } void KLN89IntPage::Knob2Left1() { if(_kln89->_mode != KLN89_MODE_CRSR || _uLinePos == 0) { KLN89Page::Knob2Left1(); } else { if(_uLinePos < 6) { // Same logic for both pages - set the ID _int_id = _int_id.substr(0, _uLinePos); // ASSERT(_uLinePos > 0); if(_uLinePos == (_int_id.size() + 1)) { _int_id += '9'; } else { _int_id[_uLinePos - 1] = _kln89->DecChar(_int_id[_uLinePos - 1], (_uLinePos == 1 ? false : true)); } } else { if(_subPage == 0) { // NO-OP - from/to field is switched by clr button, not inner knob. } else { // TODO - LNR type field. } } } } void KLN89IntPage::Knob2Right1() { if(_kln89->_mode != KLN89_MODE_CRSR || _uLinePos == 0) { KLN89Page::Knob2Right1(); } else { if(_uLinePos < 6) { // Same logic for both pages - set the ID _int_id = _int_id.substr(0, _uLinePos); // ASSERT(_uLinePos > 0); if(_uLinePos == (_int_id.size() + 1)) { _int_id += 'A'; } else { _int_id[_uLinePos - 1] = _kln89->IncChar(_int_id[_uLinePos - 1], (_uLinePos == 1 ? false : true)); } } else { if(_subPage == 0) { // NO-OP - from/to field is switched by clr button, not inner knob. } else { // TODO - LNR type field. } } } }