1
0
Fork 0

VOR symbology and Nearest VOR page.

This commit is contained in:
Stuart Buchanan 2018-02-03 20:25:48 +00:00
parent bbd99635e3
commit 339064ce31
8 changed files with 260 additions and 35 deletions

View file

@ -54,6 +54,14 @@ getTextElement : func(symbolName) {
return me._symbols[symbolName]; return me._symbols[symbolName];
}, },
highlightTextElement : func(symbolName) {
me._symbols[symbolName].highlightElement();
},
unhighlightTextElement : func(symbolName) {
me._symbols[symbolName].unhighlightElement();
},
getTextValue : func(symbolName) { getTextValue : func(symbolName) {
var sym = me._symbols[symbolName]; var sym = me._symbols[symbolName];
assert(sym != nil, "Unknown text element " ~ symbolName ~ " (check your addTextElements call?)"); assert(sym != nil, "Unknown text element " ~ symbolName ~ " (check your addTextElements call?)");

View file

@ -55,7 +55,7 @@ var NavigationMap =
var r = func(name,vis=1,zindex=nil) return caller(0)[0]; var r = func(name,vis=1,zindex=nil) return caller(0)[0];
# TODO: we'll need some z-indexing here, right now it's just random # TODO: we'll need some z-indexing here, right now it's just random
foreach(var type; [r('GRID'),r('DTO',0),r('TFC',0),r('APT'),r('DME'),r('VOR'),r('FIX',0),r('NDB'),r('GPS'),r('RTE'),r('WPT'),r('FLT'),r('WXR',0),r('APS')] ) { foreach(var type; [r('GRID'),r('DTO',0),r('TFC',0),r('APT'),r('DME'),r('VOR_FG1000'),r('NDB'),r('FIX',0),r('GPS'),r('RTE'),r('WPT'),r('FLT'),r('WXR',0),r('APS')] ) {
obj.MFDMap.addLayer( obj.MFDMap.addLayer(
factory: canvas.SymbolLayer, factory: canvas.SymbolLayer,
type_arg: type.name, type_arg: type.name,

View file

@ -51,7 +51,7 @@ var NavigationMapController =
GRID : { enabled: 0, declutter: 1, range: 20, max_range: 2000 }, GRID : { enabled: 0, declutter: 1, range: 20, max_range: 2000 },
DME : { enabled: 1, declutter: 1, range: 150, max_range: 300 }, DME : { enabled: 1, declutter: 1, range: 150, max_range: 300 },
VOR : { enabled: 1, declutter: 1, range: 150, max_range: 300 }, VOR_FG1000 : { enabled: 1, declutter: 1, range: 150, max_range: 300 },
NDB : { enabled: 1, declutter: 1, range: 15, max_range: 30 }, NDB : { enabled: 1, declutter: 1, range: 15, max_range: 30 },
FIX : { enabled: 1, declutter: 1, range: 15, max_range: 30 }, FIX : { enabled: 1, declutter: 1, range: 15, max_range: 30 },
RTE : { enabled: 1, declutter: 3, range: 2000, max_range: 2000 }, RTE : { enabled: 1, declutter: 3, range: 2000, max_range: 2000 },

View file

@ -49,7 +49,7 @@ var NavigationMapStyles =
me.Styles.FIX = {}; me.Styles.FIX = {};
me.Styles.FIX.color = [0,0,0]; # White outline me.Styles.FIX.color = [0,0,0]; # White outline
me.Styles.FIX.fill_color = [1,1,1,1]; # Black fill me.Styles.FIX.fill_color = [1,1,1,1]; # Black fill
me.Styles.FIX.scale_factor = 0.5; # 60% me.Styles.FIX.scale_factor = 0.5; # 50%
me.Styles.FIX.text_offset = [0, -12]; me.Styles.FIX.text_offset = [0, -12];
me.Styles.FIX.text_color = [0,0,0,1]; # Black text ... me.Styles.FIX.text_color = [0,0,0,1]; # Black text ...
@ -68,11 +68,19 @@ var NavigationMapStyles =
me.Styles.NDB.text_padding = 2; me.Styles.NDB.text_padding = 2;
me.Styles.NDB.text_alignment = 'center-bottom'; me.Styles.NDB.text_alignment = 'center-bottom';
me.Styles.VOR_FG1000 = {};
me.Styles.VOR = {}; me.Styles.VOR_FG1000.line_width = 1;
me.Styles.VOR.range_line_width = 2; me.Styles.VOR_FG1000.scale_factor = 1.0; # 50%
me.Styles.VOR.radial_line_width = 1; me.Styles.VOR_FG1000.circle_radius = 128;
me.Styles.VOR.scale_factor = 0.6; # 60% me.Styles.VOR_FG1000.icon_color = [0.0,0.0,0.5];
me.Styles.VOR_FG1000.circle_color = [0.2,0.8,0.8];
me.Styles.VOR_FG1000.text_offset = [0, -12];
me.Styles.VOR_FG1000.text_color = [0,0,0,1]; # Black text ...
me.Styles.VOR_FG1000.text_bgcolor = [1,1,1,1]; # ... on a white background
me.Styles.VOR_FG1000.text_mode = canvas.Text.TEXT + canvas.Text.FILLEDBOUNDINGBOX;
me.Styles.VOR_FG1000.text_padding = 2;
me.Styles.VOR_FG1000.text_alignment = 'center-bottom';
me.Styles.VOR_FG1000.font_size = 14;
me.Styles.APS = {}; me.Styles.APS = {};
me.Styles.APS.scale_factor = 0.25; me.Styles.APS.scale_factor = 0.25;

View file

@ -113,8 +113,6 @@ var NearestIntersections =
if (nav == nil) return; if (nav == nil) return;
debug.dump(nav);
if (nav.lat < 0.0) { if (nav.lat < 0.0) {
me.setTextElement("Lat", sprintf("S %.4f", -nav.lat)); me.setTextElement("Lat", sprintf("S %.4f", -nav.lat));
} else { } else {

View file

@ -10,34 +10,148 @@ var NearestVOR =
], ],
}; };
obj.topMenu(device, obj, nil);
obj.setController(fg1000.NearestVORController.new(obj, svg)); obj.setController(fg1000.NearestVORController.new(obj, svg));
# Dynamic elements. There is a single dynamic element containing the list of
# the 25 nearest intersections.
obj.select = PFD.GroupElement.new(
obj.pageName,
svg,
[ "Arrow", "ID", "CRS", "DST"],
11,
"Arrow",
1,
"ScrollTrough",
"ScrollThumb",
250 - 116
);
# Other dynamic text elements
obj.addTextElements(["Lat", "Lon", "Name", "Freq"]);
obj.topMenu(device, obj, nil);
return obj; return obj;
}, },
# Indicate which group is selected by colour of the softkeys
display_toggle : func(device, svg, mi, group) {
var bg_name = sprintf("SoftKey%d-bg",mi.menu_id);
if (me.getController().getSelectedGroup() == group) {
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
},
# Function to highlight the VOR softkey - used when CRSR is pressed to indicate
# that we're editing the VOR selection.
selectVOR : func() {
me.resetMenuColors();
var bg_name = sprintf("SoftKey%d-bg",4);
var tname = sprintf("SoftKey%d",4);
me.device.svg.getElementById(bg_name).setColorFill(0.5,0.5,0.5);
me.device.svg.getElementById(tname).setColor(0.0,0.0,0.0);
},
hideCRSR : func() {
me.select.hideCRSR();
me.unhighlightTextElement("Freq");
me.resetMenuColors();
},
offdisplay : func() { offdisplay : func() {
me._group.setVisible(0); # The Nearest... pages use the underlying navigation map.
me.mfd.NavigationMap.offdisplayPartial();
# Reset the menu colours. Shouldn't have to do this here, but # Reset the menu colours. Shouldn't have to do this here, but
# there's not currently an obvious other location to do so. # there's not currently an obvious other location to do so.
for(var i = 0; i < 12; i +=1) { me.resetMenuColors();
var name = sprintf("SoftKey%d",i);
me.device.svg.getElementById(name ~ "-bg").setColorFill(0.0,0.0,0.0);
me.device.svg.getElementById(name).setColor(1.0,1.0,1.0);
}
me.getController().offdisplay(); me.getController().offdisplay();
}, },
ondisplay : func() { ondisplay : func() {
me._group.setVisible(1);
me.mfd.setPageTitle(me.title);
me.getController().ondisplay(); me.getController().ondisplay();
# The Nearest... pages use the underlying navigation map.
me.mfd.NavigationMap.ondisplayPartial();
me.mfd.setPageTitle(me.title);
}, },
updateNavData : func(navdata) {
if ((navdata == nil) or (size(navdata) == 0)) return;
var navDataList = [];
for (var i = 0; i < size(navdata); i = i + 1) {
var nav = navdata[i];
var crsAndDst = courseAndDistance(nav);
# Display the course and distance in NM .
# 248 is the extended ASCII code for the degree symbol
var crs = sprintf("%i%c", crsAndDst[0], 248);
var dst = sprintf("%.1fnm", crsAndDst[1]);
# Convert into something we can pass straight to the UIGroup.
append(navDataList, {
Arrow : nav.id,
ID: nav.id,
CRS: crs,
DST: dst,
});
}
me.select.setValues(navDataList);
if (size(navDataList) > 0) {
me.updateNavDataItem(navdata[0]);
} else {
me.setTextElement("Name", "NONE WITHIN 200NM");
me.setTextElement("Lon", "");
me.setTextElement("Lat", "");
me.setTextElement("Frequency", "");
}
},
updateNavDataItem : func(nav) {
if (nav == nil) return;
if (nav.lat < 0.0) {
me.setTextElement("Lat", sprintf("S %.4f", -nav.lat));
} else {
me.setTextElement("Lat", sprintf("N %.4f", nav.lat));
}
if (nav.lon < 0.0) {
me.setTextElement("Lon", sprintf("W%3.4f", -nav.lon));
} else {
me.setTextElement("Lon", sprintf("E%3.4f", nav.lon));
}
me.setTextElement("Freq", sprintf("%.2f", nav.frequency / 100.0));
me.setTextElement("Name", nav.name);
# Display the DTO line to the airport
me.mfd.NavigationMap.getController().setDTOLineTarget(nav.lat, nav.lon);
},
topMenu : func(device, pg, menuitem) { topMenu : func(device, pg, menuitem) {
pg.clearMenu(); pg.clearMenu();
pg.resetMenuColors(); pg.resetMenuColors();
device.updateMenus(); pg.addMenuItem(0, "ENGINE", pg, pg.mfd.EIS.engineMenu);
pg.addMenuItem(2, "MAP", pg, pg.mfd.NavigationMap.mapMenu);
pg.addMenuItem(4, "VOR", pg,
func(dev, pg, mi) { pg.getController().selectVOR(); device.updateMenus(); }, # callback
func(svg, mi) { pg.display_toggle(device, svg, mi, NearestVORController.UIGROUP.VOR); }
);
pg.addMenuItem(5, "FREQ", pg,
func(dev, pg, mi) { pg.getController().selectFrequencies(); device.updateMenus(); }, # callback
func(svg, mi) { pg.display_toggle(device, svg, mi, NearestVORController.UIGROUP.FREQ); }
);
}, },
}; };

View file

@ -1,59 +1,154 @@
# NearestVOR Controller # NearestVOR Controller
var NearestVORController = var NearestVORController =
{ {
UIGROUP : {
NONE : 0, # No group currently selected,
VOR : 1,
FREQ : 2,
},
new : func (page, svg) new : func (page, svg)
{ {
var obj = { var obj = { parents : [ NearestVORController, MFDPageController.new(page) ] };
parents : [ NearestVORController, MFDPageController.new(page) ],
_crsrToggle : 0, obj.page = page;
_recipient : nil, obj._currentGroup = NearestVORController.UIGROUP.NONE;
_page : page, obj._crsrToggle = 0;
};
return obj; return obj;
}, },
selectVOR : func() {
me.selectGroup(NearestVORController.UIGROUP.VOR)
},
selectFrequencies : func() {
me.selectGroup(NearestVORController.UIGROUP.FREQ);
},
getSelectedGroup : func() {
return me._currentGroup;
},
selectGroup : func(grp) {
me._currentGroup = grp;
if (grp == NearestVORController.UIGROUP.VOR) me.page.select.showCRSR() else me.page.select.hideCRSR();
if (grp == NearestVORController.UIGROUP.FREQ) me.page.highlightTextElement("Freq") else me.page.unhighlightTextElement("Freq");
me._crsrToggle = 1;
},
# Input Handling # Input Handling
handleCRSR : func() { handleCRSR : func() {
me._crsrToggle = (! me._crsrToggle); me._crsrToggle = (! me._crsrToggle);
if (me._crsrToggle) { if (me._crsrToggle) {
me.page.topMenu(me.page.device, me.page, nil);
me.page.selectVOR();
me.selectVOR();
} else { } else {
me._page.hideCRSR(); me.page.hideCRSR();
} }
return emesary.Transmitter.ReceiptStatus_Finished; return emesary.Transmitter.ReceiptStatus_Finished;
}, },
handleFMSInner : func(value) { handleFMSInner : func(value) {
if (me._crsrToggle == 1) { if (me._crsrToggle == 1) {
# Scroll through whatever is the current list if (me._currentGroup == NearestVORController.UIGROUP.VOR) {
# Scroll through whatever is the current list
me.page.select.incrSmall(value);
var id = me.page.select.getValue();
var data = me.getNavDataItem(id);
if ((data != nil) and (size(data) >0)) me.page.updateNavDataItem(data[0]);
}
return emesary.Transmitter.ReceiptStatus_Finished; return emesary.Transmitter.ReceiptStatus_Finished;
} else { } else {
# Pass to the page group controller to display and scroll through the page group menu return me.page.mfd.SurroundController.handleFMSInner(value);
return me._page.mfd.SurroundController.handleFMSInner(value);
} }
}, },
handleFMSOuter : func(value) { handleFMSOuter : func(value) {
if (me._crsrToggle == 1) { if (me._crsrToggle == 1) {
if (me._currentGroup == NearestVORController.UIGROUP.VOR) {
# Scroll through whatever is the current list
me.page.select.incrSmall(value);
var id = me.page.select.getValue();
var data = me.getNavDataItem(id);
if ((data != nil) and (size(data) >0)) me.page.updateNavDataItem(data[0]);
}
return emesary.Transmitter.ReceiptStatus_Finished; return emesary.Transmitter.ReceiptStatus_Finished;
} else { } else {
# Pass to the page group controller to display and scroll through the page group menu return me.page.mfd.SurroundController.handleFMSOuter(value);
return me._page.mfd.SurroundController.handleFMSOuter(value);
} }
}, },
handleEnter : func(value) { handleEnter : func(value) {
if (me._crsrToggle == 1) { if (me._crsrToggle == 1) {
if (me._currentGroup == NearestVORController.UIGROUP.VOR) {
# Scroll through whatever is the current list
me.page.select.incrSmall(value);
var id = me.page.select.getValue();
var data = me.getNavDataItem(id);
if ((data != nil) and (size(data) >0)) me.page.updateNavDataItem(data[0]);
}
if (me._currentGroup == NearestVORController.UIGROUP.FREQ) {
var freq = me.page.getTextValue("Freq");
if (freq != nil) {
me.page.mfd.SurroundController.setStandbyNavComFreq(freq);
}
}
return emesary.Transmitter.ReceiptStatus_Finished; return emesary.Transmitter.ReceiptStatus_Finished;
} else { } else {
return emesary.Transmitter.ReceiptStatus_NotProcessed; return emesary.Transmitter.ReceiptStatus_NotProcessed;
} }
}, },
handleRange : func(val)
{
# Pass any range entries to the NavMapController
me.page.mfd.NavigationMap.getController().handleRange(val);
},
# Reset controller if required when the page is displayed or hidden # Reset controller if required when the page is displayed or hidden
ondisplay : func() { ondisplay : func() {
me.RegisterWithEmesary(); me.RegisterWithEmesary();
var fixes = me.getNearestNavData("vor");
me.page.updateNavData(fixes);
me.page.mfd.NavigationMap.getController().enableDTO(1);
me._crsrToggle = 0;
me.page.hideCRSR();
}, },
offdisplay : func() { offdisplay : func() {
me.page.mfd.NavigationMap.getController().enableDTO(0);
me.DeRegisterWithEmesary(); me.DeRegisterWithEmesary();
}, },
getNearestNavData : func(type) {
var notification = notifications.PFDEventNotification.new(
"MFD",
1,
notifications.PFDEventNotification.NavData,
{Id: "NavDataWithinRange", Value: type});
var response = me._transmitter.NotifyAll(notification);
if (! me._transmitter.IsFailed(response)) {
return notification.EventParameter.Value;
} else {
return nil;
}
},
getNavDataItem : func(id) {
# Use Emesary to get the Navigation data
var notification = notifications.PFDEventNotification.new(
"MFD",
1,
notifications.PFDEventNotification.NavData,
{Id: "NavAidByID", Value: { id: id, type: "vor"} });
var response = me._transmitter.NotifyAll(notification);
if (! me._transmitter.IsFailed(response)) {
return notification.EventParameter.Value;
} else {
return nil;
}
},
}; };

View file

@ -1491,6 +1491,7 @@ OverlayLayer.Controller = {
### ###
# set up a cache for 32x32 symbols (initialized below in load_MapStructure) # set up a cache for 32x32 symbols (initialized below in load_MapStructure)
var SymbolCache32x32 = nil; var SymbolCache32x32 = nil;
var SymbolCache256x256 = nil;
var MapStructure = { var MapStructure = {
# Generalized load methods used to load various symbols, layer controllers,... # Generalized load methods used to load various symbols, layer controllers,...
@ -1609,6 +1610,7 @@ var load_MapStructure = func {
# sets up a shared symbol cache, which will be used by all MapStructure maps and layers # sets up a shared symbol cache, which will be used by all MapStructure maps and layers
canvas.SymbolCache32x32 = SymbolCache.new(1024,32); canvas.SymbolCache32x32 = SymbolCache.new(1024,32);
canvas.SymbolCache256x256 = SymbolCache.new(1024,256);
# Find files and load them: # Find files and load them:
var contents_dir = FG_ROOT~"/Nasal/canvas/map/"; var contents_dir = FG_ROOT~"/Nasal/canvas/map/";