1
0
Fork 0

FG1000 - Improved timers

Implement single timer for all highlighting of elements.
This commit is contained in:
Stuart Buchanan 2019-03-12 20:33:35 +00:00
parent 4385b734f6
commit 6b1db73423
7 changed files with 179 additions and 189 deletions

View file

@ -22,6 +22,7 @@ var loadPFDFile = func(file) io.load_nasal(mfd_dir ~ file, "PFD");
loadPFDFile("DefaultStyle.nas");
loadPFDFile("UIElement.nas");
loadPFDFile("HighlightTimer.nas");
loadPFDFile("TextElement.nas");
loadPFDFile("HighlightElement.nas");
loadPFDFile("GroupElement.nas");
@ -92,13 +93,13 @@ getElement : func(e) {
addTextElements : func(symbols, style=nil) {
foreach (var s; symbols) {
me._textElements[s] = PFD.TextElement.new(me.pageName, me._SVGGroup, s, style);
me._textElements[s] = PFD.TextElement.new(me.pageName, me._SVGGroup, s, "", style);
}
},
addTextElement : func(e, style=nil) {
if (me._textElements[e] == nil) {
me._textElements[e] = PFD.TextElement.new(me.pageName, me._SVGGroup, e, style);
me._textElements[e] = PFD.TextElement.new(me.pageName, me._SVGGroup, e, "", style);
} else {
die("addTextElement element already exists: "~ me.pageName ~ e);
}
@ -108,8 +109,8 @@ getTextElement : func(symbolName) {
return me._textElements[symbolName];
},
highlightTextElement : func(symbolName) {
me._textElements[symbolName].highlightElement();
highlightTextElement : func(symbolName, highlightime=nil) {
me._textElements[symbolName].highlightElement(highlightime);
},
unhighlightTextElement : func(symbolName) {
@ -129,6 +130,12 @@ setTextElement : func(symbolName, value) {
sym.setValue(value);
},
setTextElements : func(symbols, value) {
foreach (var s; symbols) {
me.setTextElement(s, value);
}
},
setTextElementLat : func(symbolName, value) {
if ((value == nil) or (int(value) == nil)) {
me.setTextElement(symbolName, "_ __°__.__'");

View file

@ -114,17 +114,20 @@ var Surround =
"Nav1ID", "Nav2ID",
];
var fdTextElements = ["HeaderAPLateralArmed", "HeaderAPLateralActive", "HeaderAPVerticalArmed", "HeaderAPVerticalActive", "HeaderAPVerticalReference"];
obj.addTextElements(textElements);
if (pfd) {
obj.addTextElements(["HeaderFrom", "HeaderTo", "LegDistance", "LegBRG"]);
obj.addTextElements(["HeaderAPLateralArmed", "HeaderAPLateralActive", "HeaderAPVerticalArmed", "HeaderAPVerticalActive", "HeaderAPVerticalReference"], FD_STATUS_STYLE);
obj.addTextElements(fdTextElements, FD_STATUS_STYLE);
obj.setTextElements(fdTextElements, "");
obj._apStatus = PFD.TextElement.new(obj.pageName, svg, "HeaderAPStatus", "", AP_STATUS_STYLE);
obj._apStatusTimer = nil;
obj._apLateralStatusTimer = nil;
obj._apVerticalStatusTimer = nil;
obj._dto = PFD.HighlightElement.new(obj.pageName, svg, "HeaderDTO", "DTO");
obj._leg = PFD.HighlightElement.new(obj.pageName, svg, "HeaderActiveLeg", "Leg");
obj._old_lateral_armed = nil; # We store the previous armed values so we can detect a transtion from armed to active.
obj._old_vertical_armed = nil;
obj._ap_on = 0;
} else {
obj.addTextElements(["Header1Label", "Header1Value",
"Header2Label", "Header2Value",
@ -280,54 +283,63 @@ var Surround =
}
}
# When the Autopilot Heading or Altitude modes change we flash the appropriate annunicator for 10 seconds.
# When the Autopilot Heading or Altitude modes moves from armed to active we flash the appropriate annunicator for 10 seconds.
# Unfortunately as we use a TriggeredPropertyPublisher, we won't have both the HeaderAP[Vertical|Lateral]Active and HeaderAP[Vertical|Lateral]Armed
# values at the same time so have to save off any change in the armed values to check against.
if ((data["AutopilotHeadingMode"] != nil) and
(data["AutopilotHeadingMode"] != me.getTextValue("HeaderAPLateralActive"))) {
me.setTextElement("HeaderAPLateralActive", data["AutopilotHeadingMode"]);
# This code crashes FG at present. No idea why - perhaps reference to "me" in maketimer?
#me.highlightTextElement("HeaderAPLateralActive");
#if (me._apLateralStatusTimer == nil) me._apLateralStatusTimer = maketimer(10.0, me, me._stopLateralStatusFlashing);
#me._apLateralStatusTimer.singleShot = 1;
#me._apLateralStatusTimer.restart(10.0);
if ((data["AutopilotHeadingMode"] != "") and
((data["AutopilotHeadingMode"] == me._old_lateral_armed) or
(data["AutopilotHeadingMode"] == me.getTextValue("HeaderAPLateralArmed"))))
{
# Transition from an armed mode to a new mode, so flash
me.highlightTextElement("HeaderAPLateralActive", 10);
}
}
# When the Autopilot Heading or Altitude modes change we flash the appropriate annunicator for 10 seconds.
if ((data["AutopilotAltitudeMode"] != nil) and
(data["AutopilotAltitudeMode"] != me.getTextValue("HeaderAPVerticalActive"))) {
me.setTextElement("HeaderAPVerticalActive", data["AutopilotAltitudeMode"]);
# This code crashes FG at present. No idea why - perhaps reference to "me" in maketimer?
#me.highlightTextElement("HeaderAPVerticalActive");
#if (me._apVerticalStatusTimer == nil) me._apVerticalStatusTimer = maketimer(10.0, me, me._stopVerticalStatusFlashing);
#me._apVerticalStatusTimer.singleShot = 1;
#me._apVerticalStatusTimer.restart(10.0);
if ((data["AutopilotAltitudeMode"] != "") and
((data["AutopilotAltitudeMode"] == me._old_vertical_armed) or
(data["AutopilotAltitudeMode"] == me.getTextValue("HeaderAPVerticalArmed"))))
{
# Transition from an armed mode to a new mode, so flash
me.highlightTextElement("HeaderAPVerticalActive", 10);
}
}
if (data["AutopilotHeadingModeArmed"] != nil) me.setTextElement("HeaderAPLateralArmed", data["AutopilotHeadingModeArmed"]);
if (data["AutopilotAltitudeModeArmed"] != nil) me.setTextElement("HeaderAPVerticalArmed", data["AutopilotAltitudeModeArmed"]);
if (data["AutopilotHeadingModeArmed"] != nil) {
if (data["AutopilotHeadingModeArmed"] != me.getTextValue("HeaderAPLateralArmed")) me._old_lateral_armed = me.getTextValue("HeaderAPLateralArmed");
me.setTextElement("HeaderAPLateralArmed", data["AutopilotHeadingModeArmed"]);
}
if (data["AutopilotAltitudeModeArmed"] != nil) {
if (data["AutopilotAltitudeModeArmed"] != me.getTextValue("HeaderAPVerticalArmed")) me._old_lateral_armed = me.getTextValue("HeaderAPVerticalArmed");
me.setTextElement("HeaderAPVerticalArmed", data["AutopilotAltitudeModeArmed"]);
}
# When the Autopilot is disengaged, the AP status element flashes for 5 seconds before disappearing
if (data["AutopilotEnabled"] != nil) {
if (data["AutopilotEnabled"] == 1) {
me._apStatus.setValue("AP");
if (me._apStatusTimer != nil) {
# We were previously flashing, so stop.
me._apStatusTimer.stop();
me._apStatusTimer = nil;
me._apStatus.unhighlightElement();
}
} else {
if ((me._apStatus.getValue() != "") and (me._apStatus.isHighlighted() == 0)) {
# We were previously enabled, so we want to make the AP Status element
# flash for 5 seconds before removing it. The highlightElement()
# starts it flashing, and we use a timer to stop it.
# This code crashes FG at present. No idea why - perhaps reference to "me" in maketimer?
#me._apStatus.highlightElement();
#if (me._apStatusTimer == nil) me._apStatusTimer = maketimer(5.0, me, me._stopAPStatusFlashing);
#me._apStatusTimer.singleShot = 1;
#me._apStatusTimer.restart(5.0);
me._apStatus.setValue("");
if ((data["AutopilotEnabled"] == 1) and (me._ap_on == 0)) {
# Toggle the AP on, stopping any flashing that might be occurring.
me._apStatus.unhighlightElement();
me._apStatus.setValue("AP");
me._ap_on = 1;
}
if ((data["AutopilotEnabled"] == 0) and me._ap_on) {
# Toggle the AP off, by flashing the AP Status element for 5 seconds before removing it.
# Only do this if we're not already flashing.
me._ap_on = 0;
me._apStatus.highlightElement(5.0, "");
}
}
@ -370,22 +382,6 @@ var Surround =
}
},
_stopLateralStatusFlashing : func()
{
me.unhighlightTextElement("HeaderAPLateralActive");
},
_stopVerticalStatusFlashing : func()
{
me.unhighlightTextElement("HeaderAPVerticalActive");
},
_stopAPStatusFlashing : func()
{
me._apStatus.unhighlightElement();
me._apStatus.setValue("");
},
getCurrentPage : func()
{
var currentpage = PAGE_GROUPS[me._selectedPageGroup].pages[me._selectedPage];

View file

@ -291,25 +291,6 @@
</binding>
</key>
<key n="115">
<name>s</name>
<desc>MFD String input</desc>
<key n="903">
<name>%s</name>
<desc>MFD String input : %s</desc>
<binding>
<command>nasal</command>
<script>
var args = {'device': 2,
'notification': fg1000.FASCIA.STRING_INPUT,
'offset' : arg[0]};
fgcommand("FG1000HardKeyPushed", props.Node.new(args));
</script>
</binding>
</key>
</key>
<key n="97">
<name>a</name>
<desc>Airport Information</desc>
@ -358,22 +339,6 @@
</binding>
</key>
<key n="110">
<name>n</name>
<desc>Nearest Airport</desc>
<exit/>
<binding>
<command>nasal</command>
<script>
var args = {'device': 2,
'group': 'NrstPageGroup',
'page' : 'NearestAirports'};
fgcommand("FG1000SelectPage", props.Node.new(args));
</script>
</binding>
</key>
<key n="109">
<name>m</name>
<desc>Map</desc>

View file

@ -34,13 +34,10 @@ var DataEntryElement =
}
# State and timer for flashing highlighting of elements
obj._highlighted = 0;
obj._highlightEnabled = 0;
obj._flashTimer = nil;
obj._highlightChar = 0;
obj._flash = 0;
obj._highlightCharEnabled = 0;
obj._flashCharTimer = nil;
obj._flashChar = 0;
return obj;
},
@ -59,72 +56,57 @@ var DataEntryElement =
},
_flashElement : func() {
if (me._highlightEnabled == 0) {
me._symbol.setDrawMode(canvas.Text.TEXT);
me._symbol.setColor(me._style.NORMAL_TEXT_COLOR);
me._highlighted = 0;
} else {
if (me._highlighted == 0) {
if ((me._highlightEnabled == 1) and (me._highlightCharEnabled == 0)) {
if (me._flash == 0) {
me._symbol.setDrawMode(canvas.Text.TEXT + canvas.Text.FILLEDBOUNDINGBOX);
me._symbol.setColorFill(me._style.HIGHLIGHT_COLOR);
me._symbol.setColor(me._style.HIGHLIGHT_TEXT_COLOR);
me._highlighted = 1;
me._flash = 1;
} else {
me._symbol.setDrawMode(canvas.Text.TEXT);
me._symbol.setColor(me._style.NORMAL_TEXT_COLOR);
me._highlighted = 0;
me._flash = 0;
}
}
if (me._highlightCharEnabled == 1) {
if (me._flashChar == 0) {
me._dataEntrySymbol[me._dataEntryPos].setDrawMode(canvas.Text.TEXT + canvas.Text.FILLEDBOUNDINGBOX);
me._dataEntrySymbol[me._dataEntryPos].setColorFill(me._style.HIGHLIGHT_COLOR);
me._dataEntrySymbol[me._dataEntryPos].setColor(me._style.HIGHLIGHT_TEXT_COLOR);
me._flashChar = 1;
} else {
me._dataEntrySymbol[me._dataEntryPos].setDrawMode(canvas.Text.TEXT);
me._dataEntrySymbol[me._dataEntryPos].setColor(me._style.NORMAL_TEXT_COLOR);
me._flashChar = 0;
}
}
},
highlightElement : func() {
me._highlightEnabled = 1;
me._highlighted = 0;
me._flashElement();
me._flashTimer = maketimer(me._style.CURSOR_BLINK_PERIOD, me, me._flashElement);
me._flashTimer.start();
me._flash = 0;
PFD.HighlightTimer.startHighlight(me, -1);
},
unhighlightElement : func() {
if (me._flashTimer != nil) me._flashTimer.stop();
me._flashTimer = nil;
me._highlightEnabled = 0;
me._highlighted = 0;
me._flashElement();
me._symbol.setDrawMode(canvas.Text.TEXT);
me._symbol.setColor(me._style.NORMAL_TEXT_COLOR);
PFD.HighlightTimer.stopHighlight(me);
},
_flashCharElement : func() {
if (me._highlightCharEnabled == 0) {
me._dataEntrySymbol[me._dataEntryPos].setDrawMode(canvas.Text.TEXT);
me._dataEntrySymbol[me._dataEntryPos].setColor(me._style.NORMAL_TEXT_COLOR);
me._highlightChar = 0;
} else {
if (me._highlightChar == 0) {
me._dataEntrySymbol[me._dataEntryPos].setDrawMode(canvas.Text.TEXT + canvas.Text.FILLEDBOUNDINGBOX);
me._dataEntrySymbol[me._dataEntryPos].setColorFill(me._style.HIGHLIGHT_COLOR);
me._dataEntrySymbol[me._dataEntryPos].setColor(me._style.HIGHLIGHT_TEXT_COLOR);
me._highlightChar = 1;
} else {
me._dataEntrySymbol[me._dataEntryPos].setDrawMode(canvas.Text.TEXT);
me._dataEntrySymbol[me._dataEntryPos].setColor(me._style.NORMAL_TEXT_COLOR);
me._highlightChar = 0;
}
}
},
highlightCharElement : func() {
_highlightCharElement : func() {
me._highlightCharEnabled = 1;
me._highlightChar = 0;
me._flashCharElement();
me._flashCharTimer = maketimer(me._style.CURSOR_BLINK_PERIOD, me, me._flashCharElement);
me._flashCharTimer.start();
me._flashChar = 0;
},
unhighlightCharElement : func() {
if (me._flashCharTimer != nil) me._flashCharTimer.stop();
me._flashCharTimer = nil;
_unhighlightCharElement : func() {
me._highlightCharEnabled = 0;
me._highlightChar = 0;
me._flashCharElement();
me._dataEntrySymbol[me._dataEntryPos].setDrawMode(canvas.Text.TEXT);
me._dataEntrySymbol[me._dataEntryPos].setColor(me._style.NORMAL_TEXT_COLOR);
},
isEditable : func () { return 1; },
isInEdit : func() { return (me._dataEntryPos != -1); },
isHighlighted : func() { return me._highlightEnabled; },
enterElement : func() {
# Handle pressing enter to confirm this element.
@ -179,7 +161,7 @@ var DataEntryElement =
}
# Highlight the first character element to indicate we're editing it
me.highlightCharElement();
me._highlightCharElement();
} else {
var charSym = me._dataEntrySymbol[me._dataEntryPos];
var incr_or_decr = (value > 0) ? 1 : -1;
@ -211,8 +193,8 @@ var DataEntryElement =
if ((me._dataEntryPos == 0) and (incr_or_decr == -1)) return; # Don't scroll off the start
if ((me._dataEntryPos == me._size -1) and (incr_or_decr == 1)) return; # Don't scroll off the end
me.unhighlightCharElement();
me._unhighlightCharElement();
me._dataEntryPos = me._dataEntryPos + incr_or_decr;
me.highlightCharElement();
me._highlightCharElement();
},
};

View file

@ -33,10 +33,6 @@ var HighlightElement =
setVisible : func(vis) { me._symbol.setVisible(vis); },
_flashElement : func() {
if (me._highlightEnabled == 0) {
me._symbol.setVisible(0);
me._highlighted = 0;
} else {
if (me._highlighted == 0) {
me._symbol.setVisible(1);
me._highlighted = 1;
@ -44,25 +40,24 @@ var HighlightElement =
me._symbol.setVisible(0);
me._highlighted = 0;
}
}
},
highlightElement : func() {
me._highlightEnabled = 1;
me._highlighted = 0;
me._flashElement();
me._flashTimer = maketimer(me._style.CURSOR_BLINK_PERIOD, me, me._flashElement);
me._flashTimer.start();
# Force it to immediately display, rather than waiting for the timer
me._symbol.setVisible(1);
PFD.HighlightTimer.startHighlight(me, -1);
},
unhighlightElement : func() {
if (me._flashTimer != nil) me._flashTimer.stop();
me._flashTimer = nil;
me._highlightEnabled = 0;
me._symbol.setVisible(0);
me._highlighted = 0;
me._flashElement();
me._highlightEnabled = 0;
PFD.HighlightTimer.stopHighlight(me);
},
isEditable : func () { return 0; },
isInEdit : func() { return 0; },
enterElement : func() { return me.getValue(); },
isHighlighted : func() { return me._highlighted; },
clearElement : func() { },
editElement : func() { },
incrSmall : func(value) { },

View file

@ -0,0 +1,46 @@
# Timer used for highlight UI elements
var HighlightTimer = {
_elementList : {},
_highlightTimer : nil,
_timerPeriod : 0.5,
# Start highlighting an element for period time. Use -1 period argument to
# highlight until explicitly stopped by a call to stopHighlight.
startHighlight : func(element, period) {
me._elementList[element.getName()] = { Element: element, FlashCount : int(period / me._timerPeriod) };
if (me._highlightTimer == nil) {
me._highlightTimer = maketimer(me._timerPeriod, me, me.flashElements);
me._highlightTimer.singleShot = 0;
}
if (me._highlightTimer.isRunning == 0) {
me._highlightTimer.restart(me._timerPeriod);
}
},
stopHighlight : func(element) {
# Set the flashcount to 0 so that it is unhighlighted below.
if (me._elementList[element.getName()] != nil) me._elementList[element.getName()].FlashCount = 0;
#delete(me._elementList, element.getName());
},
flashElements : func() {
foreach (var element_name; keys(me._elementList)) {
if (me._elementList[element_name] == nil) continue;
var element = me._elementList[element_name].Element;
var flashCount = me._elementList[element_name].FlashCount;
if (flashCount == 0) {
# Calling unhighlightElement will also stop the timer, as it calls stopHighlight, above
if (element.isHighlighted() == 1) element.unhighlightElement();
} else {
me._elementList[element_name].FlashCount = flashCount - 1;
element._flashElement();
}
}
if (size(me._elementList) == 0) me._highlightTimer.stop();
},
};

View file

@ -17,53 +17,52 @@ var TextElement =
obj.setValue(value);
# State and timer for flashing highlighting of elements
# We need a separate Enabled flag as the timers are in a separate thread.
obj._highlightEnabled = 0;
obj._highlighted = 0;
obj._flashTimer = nil;
obj._flash = 0;
# Text to assign at the end of the highlight period.
# Used for annunicators that should flash and then change value.
obj._endText = nil;
return obj;
},
getName : func() { return me._name; },
getValue : func() { return me._symbol.getText(); },
getValue : func() {
if (me._symbol.getText() == nil) return ""; # Special case - canvas text elements return nil instead of empty string
return me._symbol.getText();
},
setValue : func(value) { me._symbol.setText(value); },
setVisible : func(vis) { me._symbol.setVisible(vis); },
_flashElement : func() {
if (me._highlightEnabled == 0) {
me._symbol.setDrawMode(canvas.Text.TEXT);
me._symbol.setColor(me._style.NORMAL_TEXT_COLOR);
me._highlighted = 0;
} else {
if (me._highlighted == 0) {
if (me._flash == 0) {
me._symbol.setDrawMode(canvas.Text.TEXT + canvas.Text.FILLEDBOUNDINGBOX);
me._symbol.setColorFill(me._style.HIGHLIGHT_COLOR);
me._symbol.setColor(me._style.HIGHLIGHT_TEXT_COLOR);
me._highlighted = 1;
me._flash = 1;
} else {
me._symbol.setDrawMode(canvas.Text.TEXT);
me._symbol.setColor(me._style.NORMAL_TEXT_COLOR);
me._highlighted = 0;
}
me._flash = 0;
}
},
highlightElement : func() {
me._highlightEnabled = 1;
me._highlighted = 0;
me._flashElement();
me._flashTimer = maketimer(me._style.CURSOR_BLINK_PERIOD, me, me._flashElement);
me._flashTimer.start();
highlightElement : func(highlighttime=-1, endText=nil) {
me._endText = endText;
me._highlighted = 1;
me._flash == 0;
PFD.HighlightTimer.startHighlight(me, highlighttime);
},
unhighlightElement : func() {
if (me._flashTimer != nil) me._flashTimer.stop();
me._flashTimer = nil;
me._highlightEnabled = 0;
if (me._endText != nil) me.setValue(me._endText);
me._endText = nil;
me._highlighted = 0;
me._flashElement();
me._symbol.setDrawMode(canvas.Text.TEXT);
me._symbol.setColor(me._style.NORMAL_TEXT_COLOR);
PFD.HighlightTimer.stopHighlight(me);
},
isEditable : func () { return 0; },
isInEdit : func() { return 0; },
isHighlighted : func() { return me._highlightEnabled; },
isHighlighted : func() { return me._highlighted; },
enterElement : func() { return me.getValue(); },
clearElement : func() { },
editElement : func() { },