diff --git a/Aircraft/Instruments-3d/FG1000/MFDPages/Checklist.svg b/Aircraft/Instruments-3d/FG1000/MFDPages/Checklist.svg
index e655a701f..a33ea5e89 100644
--- a/Aircraft/Instruments-3d/FG1000/MFDPages/Checklist.svg
+++ b/Aircraft/Instruments-3d/FG1000/MFDPages/Checklist.svg
@@ -23,9 +23,9 @@
borderopacity="0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="4"
- inkscape:cx="834.55454"
- inkscape:cy="123.76123"
+ inkscape:zoom="2"
+ inkscape:cx="594.53585"
+ inkscape:cy="130.11243"
inkscape:document-units="px"
inkscape:current-layer="ChecklistMainPane"
showgrid="true"
@@ -966,6 +966,30 @@
id="tspan4745"
x="946.75195"
y="694.34045">GO TO NEXT CHECKLIST?
+ * CHECKLIST NOT FINISHED *
+ * CHECKLIST FINISHED *
0) {
+ foreach (var group; groups) {
+ var grp = group.getNode("name", 1).getValue();
+ checklists[grp] = {};
+ foreach (var chklist; group.getChildren("checklist")) {
+ var items = [];
+ var title = chklist.getNode("title", 1).getValue();
+
+ # Checklists can optionally be broken down into individual pages.
+ foreach (var pg; chklist.getChildren("page")) {
+ foreach (var item; pg.getChildren("item")) {
+ var name = item.getNode("name", 1).getValue();
+ var value = item.getNode("value", 1).getValue();
+ append(items, { Name : name, Value: value, Checked: 0 });
+ }
+ }
+
+ foreach (var item; chklist.getChildren("item")) {
+ var name = item.getNode("name", 1).getValue();
+ var value = item.getNode("value", 1).getValue();
+ append(items, { Name : name, Value: value, Checked: 0 });
+ }
+
+ # items now contains a list of all the checklists for
+ checklists[grp][title] = items;
}
}
+ } else {
+ # Checklist doesn't contain any groups, so try to split into Standard
+ # and Emergency groups by looking at the checklist titles.
- foreach (var item; chklist.getChildren("item")) {
- var name = item.getNode("name", 1).getValue();
- var value = item.getNode("value", 1).getValue();
- append(items, { Name : name, Value: value, Checked: 0 });
+ foreach (var chklist; checklistprops.getChildren("checklist")) {
+ var title = chklist.getNode("title", 1).getValue();
+ var grp = "Standard";
+ var items = [];
+ if (find("emergency", string.lc(title)) != -1) {
+ grp = "EMERGENCY";
+ }
+
+ # Checklists can optionally be broken down into individual pages.
+ foreach (var pg; chklist.getChildren("page")) {
+ foreach (var item; pg.getChildren("item")) {
+ var name = item.getNode("name", 1).getValue();
+ var value = item.getNode("value", 1).getValue();
+ append(items, { Name : name, Value: value, Checked: 0 });
+ }
+ }
+
+ foreach (var item; chklist.getChildren("item")) {
+ var name = item.getNode("name", 1).getValue();
+ var value = item.getNode("value", 1).getValue();
+ append(items, { Name : name, Value: value, Checked: 0 });
+ }
+
+ # items now contains a list of all the checklists for
+ checklists[grp][title] = items;
}
-
- # items now contains a list of all the checklists for
- checklists[grp][title] = items;
}
return checklists;
diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Checklist/Checklist.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Checklist/Checklist.nas
index d1a329389..13772b25d 100644
--- a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Checklist/Checklist.nas
+++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Checklist/Checklist.nas
@@ -56,7 +56,7 @@ var Checklist =
);
obj.checklistDisplay = ChecklistGroupElement.new(
- obj.pageName,
+ obj,
svg,
16,
"ScrollTrough",
@@ -65,12 +65,14 @@ var Checklist =
);
# Other dynamic text elements
- obj.addTextElements(["GroupName", "Name", "Next"]);
+ obj.addTextElements(["GroupName", "Name", "Next", "Finished", "NotFinished"]);
# The "Next" element isn't technically dynamic, though we want it to be
# highlighted as a text element. We need to set a value for it explicitly,
# as it'll be set to an empty string otherwise.
obj.setTextElement("Next", "GO TO NEXT CHECKLIST?");
+ obj.setTextElement("Finished", "* Checklist Finished *");
+ obj.setTextElement("NotFinished", "* CHECKLIST NOT FINISHED *");
# Hide the various groups
obj.hideChecklistSelect();
@@ -173,8 +175,33 @@ var Checklist =
topMenu : func(device, pg, menuitem) {
pg.clearMenu();
pg.resetMenuColors();
+ pg.addMenuItem(0, "ENGINE", pg, pg.mfd.EIS.engineMenu);
+ pg.addMenuItem(2, "MAP", pg, pg.mfd.NavigationMap.mapMenu);
+ pg.addMenuItem(5, "CHECK", pg,
+ func(dev, pg, mi) { pg.getController().toggleCurrentItem(); dev.updateMenus(); }, # callback
+ func(svg, mi) { pg.displayCheckUncheck(svg); } # Display function
+ );
+ pg.addMenuItem(10, "EXIT", pg,
+ # This should return to the previous page...
+ func(dev, pg, mi) { dev.selectPage(pg.getMFD().getPage("NavigationMap")); },
+ );
+
+ pg.addMenuItem(11, "EMERGENCY", pg,
+ func(dev, pg, mi) { pg.getController().selectEmergencyChecklist(); }, # callback
+ );
+
device.updateMenus();
},
+
+ # Display function for the CHECK/UNCHECK softkey
+ displayCheckUncheck : func (svg) {
+ if (me.checklistDisplay.getValue()) {
+ svg.setText("UNCHECK");
+ } else {
+ svg.setText("CHECK");
+ }
+ svg.setVisible(1);
+ },
};
@@ -187,11 +214,12 @@ var Checklist =
var ChecklistGroupElement =
{
-new : func (pageName, svg, displaysize, scrollTroughElement=nil, scrollThumbElement=nil, scrollHeight=0, style=nil)
+new : func (page, svg, displaysize, scrollTroughElement=nil, scrollThumbElement=nil, scrollHeight=0, style=nil)
{
var obj = {
parents : [ ChecklistGroupElement ],
- _pageName : pageName,
+ _page : page,
+ _pageName : page.pageName,
_svg : svg,
_style : style,
_scrollTroughElement : nil,
@@ -234,20 +262,19 @@ new : func (pageName, svg, displaysize, scrollTroughElement=nil, scrollThumbElem
"Both the scroll trough element and the scroll thumb element must be defined, or neither");
if (scrollTroughElement != nil) {
- obj._scrollTroughElement = svg.getElementById(pageName ~ scrollTroughElement);
- assert(obj._scrollTroughElement != nil, "Unable to find scroll element " ~ pageName ~ scrollTroughElement);
+ obj._scrollTroughElement = svg.getElementById(obj._pageName ~ scrollTroughElement);
+ assert(obj._scrollTroughElement != nil, "Unable to find scroll element " ~ obj._pageName ~ scrollTroughElement);
}
if (scrollThumbElement != nil) {
- obj._scrollThumbElement = svg.getElementById(pageName ~ scrollThumbElement);
- assert(obj._scrollThumbElement != nil, "Unable to find scroll element " ~ pageName ~ scrollThumbElement);
+ obj._scrollThumbElement = svg.getElementById(obj._pageName ~ scrollThumbElement);
+ assert(obj._scrollThumbElement != nil, "Unable to find scroll element " ~ obj._pageName ~ scrollThumbElement);
obj._scrollBaseTransform = obj._scrollThumbElement.getTranslation();
}
if (style == nil) obj._style = PFD.DefaultStyle;
for (var i = 0; i < displaysize; i = i + 1) {
- append(obj._elements, PFD.HighlightElement.new(pageName, svg, "ItemSelect" ~ i, i, obj._style));
- #append(obj._elements, PFD.TextElement.new(pageName, svg, highlightElement ~ i, i, obj._style));
+ append(obj._elements, PFD.HighlightElement.new(obj._pageName, svg, "ItemSelect" ~ i, i, obj._style));
}
return obj;
@@ -290,8 +317,8 @@ displayGroup : func () {
var middle_element_index = math.ceil(me._size / 2);
me._pageIndex = me._crsrIndex - middle_element_index;
- if (me._crsrIndex < middle_element_index) {
- # Start of list
+ if ((size(me._values) <= me._size) or (me._crsrIndex < middle_element_index)) {
+ # Start of list or the list is too short to require scrolling
me._pageIndex = 0;
} else if (me._crsrIndex > (size(me._values) - middle_element_index - 1)) {
# End of list
@@ -315,7 +342,7 @@ displayGroup : func () {
assert(element != nil, "Unable to find element " ~ name);
if (k == "ItemSelect") {
- # Display if this is the cursor eleemtn
+ # Display if this is the cursor element
element.setVisible(crsr);
} else if (k == "ItemTick") {
# Check the box if appropriate
@@ -384,6 +411,27 @@ displayGroup : func () {
me._scrollBaseTransform[1] + me._scrollHeight * (me._crsrIndex / (size(me._values) -1))
]);
}
+
+ # Indicate whether we're finished with this checklist or not
+ var finished = me.isComplete();
+ me._page.getTextElement("Finished").setVisible(finished);
+ me._page.getTextElement("NotFinished").setVisible(! finished);
+
+ # Update the softkeys, which will in particular change the CHECK/UNCHECK softkeys
+ # appropriately.
+ me._page.device.updateMenus();
+},
+
+isComplete : func() {
+ var finished = 1;
+ foreach (var entry; me._values) {
+ if (entry["ItemTick"] == 0) {
+ finished = 0;
+ break;
+ }
+ }
+
+ return finished;
},
# Methods to add dynamic elements to the group. Must be called in the
@@ -402,8 +450,8 @@ showCRSR : func() {
},
hideCRSR : func() {
if (me._crsrEnabled == 0) return;
- me.displayGroup();
me._crsrEnabled = 0;
+ me.displayGroup();
},
setCRSR : func(index) {
me._crsrIndex = math.min(index, size(me._values) -1);
@@ -423,11 +471,11 @@ isCursorOnDataEntryElement : func() {
enterElement : func() {
if (me._crsrEnabled == 0) return;
- # ENT on an element of the checklist simply toggles the item itself,
+ # ENT on an element of the checklist checks the box,
# indicated by whether the check mark is visible or not.
var name = me._pageName ~ "ItemTick" ~ (me._crsrIndex - me._pageIndex);
var element = me._svg.getElementById(name);
- element.setVisible(! element.getVisible());
+ element.setVisible(1);
return element.getVisible();
},
getValue : func() {
@@ -444,7 +492,13 @@ setValue : func(idx, key, value) {
},
clearElement : func() {
if (me._crsrEnabled == 0) return;
- me._elements[me._crsrIndex - me._pageIndex].clearElement();
+
+ # CLR on an element of the checklist unchecks the box,
+ # indicated by whether the check mark is visible or not.
+ var name = me._pageName ~ "ItemTick" ~ (me._crsrIndex - me._pageIndex);
+ var element = me._svg.getElementById(name);
+ element.setVisible(0);
+ return element.getVisible();
},
incrSmall : func(value) {
if (me._crsrEnabled == 0) return;
diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Checklist/ChecklistController.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Checklist/ChecklistController.nas
index 2c01ce07b..c27bb9ca1 100644
--- a/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Checklist/ChecklistController.nas
+++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFDPages/Checklist/ChecklistController.nas
@@ -50,6 +50,10 @@ var ChecklistController =
selectItems : func() {
me.selectGroup(ChecklistController.UIGROUP.ITEMS);
},
+ selectNext : func() {
+ me.selectGroup(ChecklistController.UIGROUP.NEXT);
+ },
+
getSelectedGroup : func() {
return me._currentGroup;
@@ -85,6 +89,26 @@ var ChecklistController =
}
},
+ selectEmergencyChecklist : func() {
+ # Select the EMERGENCY checklist group, if available.
+ var emergency_labels = ["EMERGENCY", "Emergency", "emergency"];
+ var group = nil;
+ foreach (var l; emergency_labels) {
+ if (me._checklists[l] != nil) {
+ group = l;
+ break;
+ }
+ }
+
+ if (group != nil) {
+ me._group_selected = group;
+ me._list_selected = keys(me._checklists[me._group_selected])[0];
+ me._page.hideGroupSelect();
+ me._page.displayChecklist(me._group_selected, me._list_selected, me._checklists);
+ me.selectChecklist();
+ }
+ },
+
# Input Handling
handleCRSR : func() {
me._crsrToggle = (! me._crsrToggle);
@@ -129,6 +153,11 @@ var ChecklistController =
},
handleFMSOuter : func(value) {
if (me._crsrToggle == 1) {
+ # Manual explicitly documents that _either_ FMS knob may be used to scroll through the checklist.
+ # However, that means that there is no way to navigate from the checklist itself other
+ # than to disable and then re-enable the CRSR. Odd.
+ if (me._currentGroup == ChecklistController.UIGROUP.ITEMS) return me.handleFMSInner(value);
+
var incr_or_decr = (value > 0) ? 1 : -1;
var idx = me._currentGroup + incr_or_decr;
if (idx < 0) idx = 0;
@@ -164,12 +193,22 @@ var ChecklistController =
}
if (me._currentGroup == ChecklistController.UIGROUP.ITEMS) {
- # Toggle the status of the selected Checklist item
+ # Check the selected Checklist item
+ me.checkCurrentItem();
var idx = me._page.checklistDisplay.getCRSR();
- var checked = me._page.checklistDisplay.getValue();
- me._checklists[me._group_selected][me._list_selected][idx]["Checked"] = me._page.checklistDisplay.enterElement();
- me._page.displayChecklist(me._group_selected, me._list_selected, me._checklists);
- me._page.checklistDisplay.incrSmall(1);
+
+ if ((idx == (size(me._checklists[me._group_selected][me._list_selected]) -1)) and
+ me._page.checklistDisplay.isComplete()) {
+ # If we're right at the end of this checklist then move onto the "Next Checklist"
+ # button. Manual isn't clear on whether this is only if the checklist is complete,
+ # but we will assume that is the case.
+ me.selectNext();
+ } else {
+ # Automatically go to the next item.
+ me.handleFMSInner(1);
+ }
+
+ return emesary.Transmitter.ReceiptStatus_Finished;
}
if (me._currentGroup == ChecklistController.UIGROUP.NEXT) {
@@ -182,6 +221,7 @@ var ChecklistController =
if (idx < size(lists)) {
me._list_selected = lists[idx];
+ me._page.checklistDisplay.setCRSR(0);
me._page.displayChecklist(me._group_selected, me._list_selected, me._checklists);
me.selectItems();
}
@@ -194,6 +234,39 @@ var ChecklistController =
}
},
+ handleClear : func() {
+ if ((me._crsrToggle == 1) and
+ (me._currentGroup == ChecklistController.UIGROUP.ITEMS)) {
+ # Uncheck the selected Checklist item
+ me.clearCurrentItem();
+ return emesary.Transmitter.ReceiptStatus_Finished;
+ }
+
+ return emesary.Transmitter.ReceiptStatus_NotProcessed;
+ },
+
+ checkCurrentItem : func() {
+ me._page.checklistDisplay.enterElement();
+ var idx = me._page.checklistDisplay.getCRSR();
+ me._checklists[me._group_selected][me._list_selected][idx]["Checked"] = 1;
+ me._page.displayChecklist(me._group_selected, me._list_selected, me._checklists);
+ },
+
+ clearCurrentItem : func() {
+ me._page.checklistDisplay.clearElement();
+ var idx = me._page.checklistDisplay.getCRSR();
+ me._checklists[me._group_selected][me._list_selected][idx]["Checked"] = 0;
+ me._page.displayChecklist(me._group_selected, me._list_selected, me._checklists);
+ },
+
+ toggleCurrentItem : func() {
+ if (me._page.checklistDisplay.getValue()) {
+ me.clearCurrentItem();
+ } else {
+ me.checkCurrentItem();
+ }
+ },
+
# Retrieve the current set of checklists from the system.
getChecklists : func() {
var notification = notifications.PFDEventNotification.new(
diff --git a/Nasal/canvas/PFD/GroupElement.nas b/Nasal/canvas/PFD/GroupElement.nas
index 8eeab874e..69745e262 100644
--- a/Nasal/canvas/PFD/GroupElement.nas
+++ b/Nasal/canvas/PFD/GroupElement.nas
@@ -108,11 +108,11 @@ displayGroup : func () {
# In these cases, we let the cursor move to the top or bottom of the list.
# Determine the middle element
- var middle_element_index = int(me._size / 2);
+ var middle_element_index = math.ceil(me._size / 2);
me._pageIndex = me._crsrIndex - middle_element_index;
- if (me._crsrIndex < middle_element_index) {
- # Start of list
+ if ((size(me._values) <= me._size) or (me._crsrIndex < middle_element_index)) {
+ # Start of list or the list is too short to require scrolling
me._pageIndex = 0;
} else if (me._crsrIndex > (size(me._values) - middle_element_index - 1)) {
# End of list