diff --git a/Aircraft/Instruments-3d/FG1000/MFDPages/NearestAirportsInfoPFD.svg b/Aircraft/Instruments-3d/FG1000/MFDPages/NearestAirportsInfoPFD.svg new file mode 100644 index 000000000..423746a82 --- /dev/null +++ b/Aircraft/Instruments-3d/FG1000/MFDPages/NearestAirportsInfoPFD.svg @@ -0,0 +1,231 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + KSFO + AIRPORT NAME + AIRPORT INFORMATION + FACILITY + + 10999FT + TIME + REGION + N 38.34 + N 38.34 + + FACILITY + BACK + + + diff --git a/Aircraft/Instruments-3d/FG1000/MFDPages/NearestAirportsPFD.svg b/Aircraft/Instruments-3d/FG1000/MFDPages/NearestAirportsPFD.svg new file mode 100644 index 000000000..b407d5c18 --- /dev/null +++ b/Aircraft/Instruments-3d/FG1000/MFDPages/NearestAirportsPFD.svg @@ -0,0 +1,396 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + KSFO + VFR + NEAREST AIRPORTS + 123.475 + TOWER + 189 + 12.3NM + RNWY + + 10999FT + KSFO + VFR + 123.475 + TOWER + 189 + 12.3NM + RNWY + 10999FT + + KSFO + VFR + 123.475 + TOWER + 189 + 12.3NM + RNWY + 10999FT + + + + + + + + diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPage.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPage.nas index 1ff3254cc..fde9cd3dc 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPage.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPage.nas @@ -109,7 +109,7 @@ getTextElement : func(symbolName) { return me._textElements[symbolName]; }, -highlightTextElement : func(symbolName, highlightime=nil) { +highlightTextElement : func(symbolName, highlightime=-1) { me._textElements[symbolName].highlightElement(highlightime); }, diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFD.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFD.nas new file mode 100644 index 000000000..21fc6a98d --- /dev/null +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFD.nas @@ -0,0 +1,208 @@ +# Copyright 2018 Stuart Buchanan +# This file is part of FlightGear. +# +# FlightGear 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. +# +# FlightGear 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 FlightGear. If not, see . +# +# NearestAirportsPFD +var NearestAirportsPFD = +{ + new : func (mfd, myCanvas, device, svg) + { + var obj = { + parents : [ + NearestAirportsPFD, + MFDPage.new(mfd, myCanvas, device, svg, "NearestAirportsPFD", "NRST - NEAREST AIRPORTS") + ], + }; + + obj.setController(fg1000.NearestAirportsPFDController.new(obj, svg)); + + # Dynamic elements. There are 2 different sets of dynamic elements: + # + # Nearest Airports - this is a scrolling list of up to 25 airports within 200nm, shown 3 at a time. + # Airport Information - A page of more detailed information displaying details of the selected airport + # + # Selection is via the ENT key or the FMS knob + + obj.airportSelect = PFD.GroupElement.new( + obj.pageName, + svg, + [ "ID", "BRG", "DST", "APP", "CommsType", "CommsFreq", "RWY"], + 3, + "ID", + 0, + "ScrollBar", + "Scroll", + 140 + ); + + # Dynamic text elements for the Airport Info pane. + obj.addTextElements(["InfoID", "InfoName", + "InfoFacility", + "InfoUsage", "InfoTime", "InfoAlt", + "InfoRegion", + "InfoLat", "InfoLon", "InfoBack"]); + + obj.setTextElement("InfoBack", "BACK"); + obj._visible = 0; + obj._NO_AIRPORTS = "NONE WITHIN 200NM"; + obj.getElement("Group").setVisible(0); + obj.getElement("Info").setVisible(0); + + return obj; + }, + + visible : func() { + return me._visible; + }, + toggleDisplay : func() { + if (me.visible()) { + me.offdisplay(); + } else { + me.ondisplay(); + } + }, + offdisplay : func() { + me.getElement("Group").setVisible(0); + me.getElement("Info").setVisible(0); + me._visible = 0; + me.getController().offdisplay(); + }, + ondisplay : func() { + me._visible = 1; + me.getController().ondisplay(); + me.displayNearest(); + }, + displayNearest : func() { + me.getElement("Group").setVisible(1); + me.getElement("Info").setVisible(0); + }, + displayInfo : func() { + me.getElement("Group").setVisible(0); + me.getElement("Info").setVisible(1); + me.highlightTextElement("InfoBack"); + }, + updateAirports : func(apts) { + + var airportlist = []; + for (var i = 0; i < size(apts); i = i + 1) { + var apt = apts[i]; + var crsAndDst = courseAndDistance(apt); + + # Display the course and distance in NM . + var crs = sprintf("%i°", crsAndDst[0]); + var dst = sprintf("%.1fnm", crsAndDst[1]); + + # We need to derive various non-trivial pieces of information: + # - Maximum runway Length + # - Approach type - VFR, ILS, NDB + # - Approach, Tower or Unicom frequency + + var max_rwy = 0; + var app_type = "VFR"; + var freq_type = ""; + var freq = ""; + + foreach(var rwy; keys(apt.runways)) { + var rwy_info = apt.runways[rwy]; + max_rwy = math.max(max_rwy, rwy_info.length); + + # This is the best we can do at present for approach types. + if (rwy_info.ils_frequency_mhz != nil) app_type = "ILS"; + } + + var apt_comms = apt.comms(); + foreach (var c; apt_comms) { + if (string.icmp(c.ident, "Approach") or + string.icmp(c.ident, "APP") or + string.icmp(c.ident, "APPROACH") ) { + + freq_type = "APPROACH"; + freq = sprintf("%.3f", c.frequency); + + # Fine - we've got the best possible frequency, so break out + # to stop any Tower frequencies from over-writing. + break; + } + + if (string.icmp(c.ident, "Tower") or + string.icmp(c.ident, "TWR") or + string.icmp(c.ident, "Tower") ) { + freq_type = "TOWER"; + freq = sprintf("%.3f", c.frequency); + } + + # Only select a Unicom / Traffic if there's nothing found already + if ((freq_type == "") and + (string.icmp(c.ident, "Unicom") or + string.icmp(c.ident, "UNICOM") )) { + freq_type = "UNICOM"; + freq = sprintf("%.3f", c.frequency); + } + } + + # Convert into something we can pass straight to the UIGroup. + append(airportlist, { + ID: apt.id, + BRG: crs, + DST: dst, + APP: app_type, + CommsType : freq_type, + CommsFreq : freq, + RWY : sprintf("%ift", 3.28 * max_rwy) + }); + } + + + if (size(airportlist) == 0) { + # Blank value if in the middle of nowhere + append(airportlist, { + ID: me._NO_AIRPORTS, + BRG: "", + DST: "", + APP: "", + CommsType : "", + CommsFreq : "", + RWY : "" + }); + } + + me.airportSelect.setValues(airportlist); + }, + updateAirportData : func(apt) { + + if (apt == nil) return; + + me.setTextElement("InfoID", apt.id); + me.setTextElement("InfoName", string.uc(apt.name)); + me.setTextElement("InfoFacility", ""); + + if (string.imatch(apt.name, "private") or string.imatch(apt.name, "pvt")) { + me.setTextElement("InfoUsage", "PRIVATE"); + } else { + me.setTextElement("InfoUsage", "PUBLIC"); + } + + me.setTextElement("InfoTime", ""); + me.setTextElement("InfoAlt", sprintf("%ift", 3.28 * apt.elevation)); + me.setTextElementLat("InfoLat", apt.lat); + me.setTextElementLon("InfoLon", apt.lon); + + }, + getSelectedAirportID : func() { + var id = me.airportSelect.getValue(); + if (id == me._NO_AIRPORTS) id = nil; + return id; + }, +}; diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFDController.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFDController.nas new file mode 100644 index 000000000..f368a1f49 --- /dev/null +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFDController.nas @@ -0,0 +1,173 @@ +# Copyright 2018 Stuart Buchanan +# This file is part of FlightGear. +# +# FlightGear 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. +# +# FlightGear 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 FlightGear. If not, see . +# +# NearestAirportsPFD Controller +var NearestAirportsPFDController = +{ + MODE : { + NONE : 0, # Nothing displayed + NEAREST : 1, # Nearest Airports pane visible + INFO : 2, # Airport Info pane visible + }, + + new : func (page, svg) + { + var obj = { parents : [ NearestAirportsPFDController, MFDPageController.new(page) ] }; + + # Current active UI group. + obj.page = page; + obj._mode = NearestAirportsPFDController.MODE.NONE; + obj._crsrToggle = 0; + return obj; + }, + + selectNearest : func() { + me.selectGroup(NearestAirportsPFDController.MODE.NEAREST) + }, + selectInfo : func() { + me.selectGroup(NearestAirportsPFDController.MODE.INFO); + }, + selectNone : func() { + me.selectGroup(NearestAirportsPFDController.MODE.NONE); + }, + getSelectedMode : func() { + return me._mode; + }, + selectGroup : func(grp) { + me._mode = grp; + if (grp == NearestAirportsPFDController.MODE.NONE) { + me.page.offdisplay(); + } + if (grp == NearestAirportsPFDController.MODE.NEAREST) { + me.page.displayNearest(); + } + if (grp == NearestAirportsPFDController.MODE.INFO) { + var aptdata = me.getAirport(me.page.getSelectedAirportID()); + me.page.updateAirportData(aptdata); + me.page.displayInfo(); + } + }, + + # Input Handling + handleCRSR : func(value) { + me._crsrToggle = (! me._crsrToggle); + if (me._crsrToggle) { + me.page.airportSelect.showCRSR(); + } else { + # Hide the cursor and reset any highlighting + me.page.airportSelect.hideCRSR(); + } + return emesary.Transmitter.ReceiptStatus_Finished; + }, + handleFMSInner : func(value) { + if (me._crsrToggle and (me._mode == NearestAirportsPFDController.MODE.NEAREST)) { + # Scroll through the nearest airports list + me.page.airportSelect.incrSmall(value); + return emesary.Transmitter.ReceiptStatus_Finished; + } else { + return emesary.Transmitter.ReceiptStatus_NotProcessed; + } + }, + handleFMSOuter : func(value) { + return me.handleFMSInner(value); + }, + handleEnter : func(value) { + if (me._mode == NearestAirportsPFDController.MODE.NEAREST) { + # Enable the cursor if it's not already enabled. + me._crsrToggle = 1; + me.page.airportSelect.showCRSR(); + + # Load the current airport and display it + if (me.page.getSelectedAirportID() != nil) { + me.selectInfo(); + } + return emesary.Transmitter.ReceiptStatus_Finished; + } else if (me._mode == NearestAirportsPFDController.MODE.INFO) { + # Pressing Enter on the Info window hides the info window and selects the + # next airport on the list. + # Load the current airport and display it + me.selectNearest(); + me.page.airportSelect.incrSmall(1); + return emesary.Transmitter.ReceiptStatus_Finished; + } else { + return emesary.Transmitter.ReceiptStatus_NotProcessed; + } + }, + handleClear : func(value) { + if (me._mode == NearestAirportsPFDController.MODE.NEAREST) { + # Finished - unload the page. + me.page.offdisplay(); + return emesary.Transmitter.ReceiptStatus_Finished; + } else if (me._mode == NearestAirportsPFDController.MODE.INFO) { + # Pressing Clear on the Info window hides the info window and selects the + # next airport on the list, just like Enter + # Load the current airport and display it + me.selectNearest(); + me.page.airportSelect.incrSmall(1); + return emesary.Transmitter.ReceiptStatus_Finished; + } else { + return emesary.Transmitter.ReceiptStatus_NotProcessed; + } + }, + + # Reset controller if required when the page is displayed or hidden + ondisplay : func() { + me.RegisterWithEmesary(); + me.getNearestAirportsPFD(); + me.selectNearest(); + }, + offdisplay : func() { + me.DeRegisterWithEmesary(); + }, + + getNearestAirportsPFD : func() { + var notification = notifications.PFDEventNotification.new( + "MFD", + me.getDeviceID(), + notifications.PFDEventNotification.NavData, + {Id: "NearestAirports", Value: nil}); + + var response = me._transmitter.NotifyAll(notification); + + if (! me._transmitter.IsFailed(response)) { + me.page.updateAirports(notification.EventParameter.Value); + } else { + return nil; + } + }, + + getAirport : func(id) { + # Use Emesary to get the airport + var notification = notifications.PFDEventNotification.new( + "MFD", + me.getDeviceID(), + notifications.PFDEventNotification.NavData, + {Id: "AirportByID", Value: id}); + + var response = me._transmitter.NotifyAll(notification); + + if (! me._transmitter.IsFailed(response)) { + var apt_list = notification.EventParameter.Value; + if ((apt_list != nil) and (size(apt_list) > 0)) { + return apt_list[0]; + } else { + return nil; + } + } else { + return nil; + } + }, +}; diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFDOptions.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFDOptions.nas new file mode 100644 index 000000000..8b4432dca --- /dev/null +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFDOptions.nas @@ -0,0 +1,44 @@ +# Copyright 2018 Stuart Buchanan +# This file is part of FlightGear. +# +# FlightGear 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. +# +# FlightGear 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 FlightGear. If not, see . +# +# NearestAirportsPFD Options +var NearestAirportsPFDOptions = +{ + new : func() { + var obj = { parents : [NearestAirportsPFDOptions] }; + obj.Options= {}; + obj.loadOptions(); + return obj; + }, + + getOption : func(type) { + return me.Options[type]; + }, + + setOption : func(type, name, value) { + me.Options[type][name] = value; + }, + + loadOptions : func() { + me.clearOptions(); + me.Options.APS = {}; + }, + + clearOptions : func() { + me.Options = {}; + }, + +}; diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFDStyles.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFDStyles.nas new file mode 100644 index 000000000..0c687d14d --- /dev/null +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/NearestAirportsPFD/NearestAirportsPFDStyles.nas @@ -0,0 +1,44 @@ +# Copyright 2018 Stuart Buchanan +# This file is part of FlightGear. +# +# FlightGear 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. +# +# FlightGear 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 FlightGear. If not, see . +# +# NearestAirportsPFD Styles +var NearestAirportsPFDStyles = +{ + new : func() { + var obj = { parents : [ NearestAirportsPFDStyles ]}; + obj.Styles = {}; + obj.loadStyles(); + return obj; + }, + + getStyle : func(type) { + return me.Styles[type]; + }, + + setStyle : func(type, name, value) { + me.Styles[type][name] = value; + }, + + loadStyles : func() { + me. clearStyles(); + me.Styles.XXX = {}; + }, + + clearStyles : func() { + me.Styles = {}; + }, + +}; diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/PFDInstruments/PFDInstruments.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/PFDInstruments/PFDInstruments.nas index c6f323b4a..9e186c6b7 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/PFDInstruments/PFDInstruments.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/PFDInstruments/PFDInstruments.nas @@ -131,11 +131,29 @@ var PFDInstruments = pg.addMenuItem(7, "XPDR", pg, pg.mfd.PFDInstruments.transponderMenu); pg.addMenuItem(8, "IDENT", pg, pg.mfd.PFDInstruments.setIdent); # TODO pg.addMenuItem(9, "TMR/REF", pg); # TODO - pg.addMenuItem(10, "NRST", pg); # TODO + pg.addMenuItem(10, "NRST", pg, pg.mfd.PFDInstruments.toggleNRST, func(svg, mi) { pg.mfd.PFDInstruments.toggleNRSTDisplay(device, pg, svg, mi); } ); pg.addMenuItem(11, "ALERTS", pg); # TODO device.updateMenus(); }, + toggleNRST : func (device, pg, mi) { + pg.mfd.NearestAirports.toggleDisplay(); + device.updateMenus(); + }, + + toggleNRSTDisplay : func(device, pg, svg, mi) { + var bg_name = sprintf("SoftKey%d-bg",mi.menu_id); + if (pg.mfd.NearestAirports.visible()) { + device.svg.getElementById(bg_name).setColorFill(0.5,0.5,0.5); + svg.setColor(0.0,0.0,0.0); + } else { + device.svg.getElementById(bg_name).setColorFill(0.0,0.0,0.0); + svg.setColor(1.0,1.0,1.0); + } + svg.setText(mi.title); + svg.setVisible(1); # display function + }, + insetMenu : func(device, pg, menuitem) { # Switch on the inset Map pg.setInsetMapVisible(1); diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/PFDInstruments/PFDInstrumentsController.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/PFDInstruments/PFDInstrumentsController.nas index 020951079..1b9ec168a 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/PFDInstruments/PFDInstrumentsController.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/PFDInstruments/PFDInstrumentsController.nas @@ -126,39 +126,6 @@ var PFDInstrumentsController = }, # Input Handling - handleCRSR : func() { - me._crsrToggle = (! me._crsrToggle); - if (me._crsrToggle) { - } else { - #me.page.hideCRSR(); - } - return emesary.Transmitter.ReceiptStatus_Finished; - }, - handleFMSInner : func(value) { - if (me._crsrToggle == 1) { - # Scroll through whatever is the current list - return emesary.Transmitter.ReceiptStatus_Finished; - } else { - # Pass to the page group controller to display and scroll through the page group menu - #return me.page.mfd.SurroundController.handleFMSInner(value); - } - }, - handleFMSOuter : func(value) { - if (me._crsrToggle == 1) { - return emesary.Transmitter.ReceiptStatus_Finished; - } else { - # Pass to the page group controller to display and scroll through the page group menu - #return me.page.mfd.SurroundController.handleFMSOuter(value); - } - }, - handleEnter : func(value) { - if (me._crsrToggle == 1) { - return emesary.Transmitter.ReceiptStatus_Finished; - } else { - return emesary.Transmitter.ReceiptStatus_NotProcessed; - } - }, - handleRange : func(val) { if (val >0) { diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Surround/Surround.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Surround/Surround.nas index 9174335e0..4e46c357a 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Surround/Surround.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Surround/Surround.nas @@ -179,7 +179,7 @@ var Surround = obj.hideMenu(); - obj.setController(fg1000.SurroundController.new(obj, svg)); + obj.setController(fg1000.SurroundController.new(obj, svg, pfd)); return obj; }, @@ -425,6 +425,9 @@ var Surround = # Function to change a page based on the selection loadPage : func() { + # Not valid for the PFD. + if (me.pfd) return; + var pageToLoad = PAGE_GROUPS[me._selectedPageGroup].pages[me._selectedPage]; var page = me.getMFD().getPage(pageToLoad); @@ -442,6 +445,9 @@ var Surround = }, showMenu : func() { + # Not valid for the PFD. + if (me.pfd) return; + foreach(var pageGroup; PAGE_GROUPS) { if (PAGE_GROUPS[me._selectedPageGroup].label == pageGroup.label) diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Surround/SurroundController.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Surround/SurroundController.nas index 1ee501dc6..63f2595c8 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Surround/SurroundController.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Surround/SurroundController.nas @@ -17,12 +17,13 @@ # Surround Controller var SurroundController = { - new : func (page, svg) + new : func (page, svg, pfd) { var obj = { parents : [ SurroundController ], _recipient : nil, _page : page, + _pfd : pfd, _comselected : 1, _navselected : 1, _com1active : 0.0, @@ -458,6 +459,7 @@ var SurroundController = # handleFMSOuter : func(val) { + if (me._pfd) return emesary.Transmitter.ReceiptStatus_NotProcessed; if (me._page.isMenuVisible()) { # Change page group me._page.incrPageGroup(val); @@ -468,6 +470,7 @@ var SurroundController = handleFMSInner : func(val) { + if (me._pfd) return emesary.Transmitter.ReceiptStatus_NotProcessed; if (me._page.isMenuVisible()) { # Change page group me._page.incrPage(val); diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/PFD.nas b/Aircraft/Instruments-3d/FG1000/Nasal/PFD.nas index 7d9f6e6ac..2c56be1f1 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/PFD.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/PFD.nas @@ -25,6 +25,7 @@ var PFDDisplay = EIS : nil, PFDInstruments : nil, Surround : nil, + NearestAirports : nil, _pageList : {}, _fg1000 : fg1000instance, _canvas : myCanvas, @@ -39,6 +40,11 @@ var PFDDisplay = io.load_nasal(nasal_dir ~ "MFDPages/DirectTo/DirectTo.nas", "fg1000"); io.load_nasal(nasal_dir ~ "MFDPages/DirectTo/DirectToController.nas", "fg1000"); + io.load_nasal(nasal_dir ~ "MFDPages/NearestAirportsPFD/NearestAirportsPFD.nas", "fg1000"); + io.load_nasal(nasal_dir ~ "MFDPages/NearestAirportsPFD/NearestAirportsPFDStyles.nas", "fg1000"); + io.load_nasal(nasal_dir ~ "MFDPages/NearestAirportsPFD/NearestAirportsPFDOptions.nas", "fg1000"); + io.load_nasal(nasal_dir ~ "MFDPages/NearestAirportsPFD/NearestAirportsPFDController.nas", "fg1000"); + obj.ConfigStore = obj._fg1000.getConfigStore(); obj._svg = myCanvas.createGroup("softkeys"); @@ -70,6 +76,13 @@ var PFDDisplay = '/Aircraft/Instruments-3d/FG1000/MFDPages/DirectToPFD.svg', {'font-mapper': fontmapper}); + canvas.parsesvg(obj._svg, + '/Aircraft/Instruments-3d/FG1000/MFDPages/NearestAirportsPFD.svg', + {'font-mapper': fontmapper}); + + canvas.parsesvg(obj._svg, + '/Aircraft/Instruments-3d/FG1000/MFDPages/NearestAirportsInfoPFD.svg', + {'font-mapper': fontmapper}); canvas.parsesvg(obj._svg, '/Aircraft/Instruments-3d/FG1000/MFDPages/SurroundPFD.svg', @@ -84,6 +97,8 @@ var PFDDisplay = obj._DTO = fg1000.DirectTo.new(obj, myCanvas, obj._MFDDevice, obj._svg); obj._DTO.getController().RegisterWithEmesary(); + obj.NearestAirports = fg1000.NearestAirportsPFD.new(obj, myCanvas, obj._MFDDevice, obj._svg); + obj._MFDDevice.RegisterWithEmesary(); # Surround dynamic elements @@ -94,11 +109,6 @@ var PFDDisplay = obj.Surround = fg1000.Surround.new(obj, myCanvas, obj._MFDDevice, obj._svg, 1); obj.SurroundController = obj.Surround.getController(); - # Engine Information System. A special case as it's always displayed on the MFD. - # Note that it is passed in on the constructor - obj.EIS = EIS_Class.new(obj, myCanvas, obj._MFDDevice, obj._svg); - obj.addPage("EIS", obj.EIS); - obj.PFDInstruments = fg1000.PFDInstruments.new(obj, myCanvas, obj._MFDDevice, obj._svg); obj.addPage("PFDInstruments", obj.PFDInstruments); obj.PFDInstruments.topMenu(obj._MFDDevice, obj.PFDInstruments, nil); diff --git a/Nasal/canvas/PFD/GroupElement.nas b/Nasal/canvas/PFD/GroupElement.nas index 69745e262..34bfb75cd 100644 --- a/Nasal/canvas/PFD/GroupElement.nas +++ b/Nasal/canvas/PFD/GroupElement.nas @@ -17,7 +17,7 @@ new : func (pageName, svg, elementNames, displaysize, highlightElement, arrow=0, _elementNames : elementNames, # The size of the group. For each of the ._elementNames hash values there - # must be an SVG Element [pageName][elementName]{0...pageSize} + # must be an SVG Element [pageName][elementName]{0...(displaysize-1)} _size : displaysize, # ElementName to be highlighted. Must be an hash value from ._elementNames @@ -54,6 +54,14 @@ new : func (pageName, svg, elementNames, displaysize, highlightElement, arrow=0, ((scrollTroughElement != nil) and (scrollThumbElement != nil)), "Both the scroll trough element and the scroll thumb element must be defined, or neither"); + # Verify that all values exist. + for (var i = 0; i < displaysize; i = i + 1) { + foreach (var element; elementNames) { + var elementName = obj._pageName ~ element ~ i; + assert(obj._svg.getElementById(elementName) != nil, "Unable to find element " ~ elementName); + } + } + if (scrollTroughElement != nil) { obj._scrollTroughElement = svg.getElementById(pageName ~ scrollTroughElement); assert(obj._scrollTroughElement != nil, "Unable to find scroll element " ~ pageName ~ scrollTroughElement);