Plugin Support
The FMC framework includes support for extending or replacing functionality through the plugin system.
If multiple FMC plugins are registered, then there is no defined order in which they run. They will be ran in the order on which they load, which is unpredictable and can change due to performance. This may be especially problematic where multiple plugins attempt to handle events as one plugin may be considered to have handled the event, when the desired effect is that the other plugin does so.
Considerations for instrument developers when planning plugin support
When an instrument developer is planning to support the use of plugins with the FMC framework, they must consider the functions that they pass to the plugin, along with the page classes provided in a plugin package.
To allow for plugin developers to extend the FMC in any capacity, instrument developers must make available a function which provides an FmcScreenPluginContext<InstrumentFmcPage, InstrumentFmcEvents>
where InstrumentFmcPage
is the page class used within the instrument (i.e. Wt21FmcPage
), and InstrumentFmcEvents
is the interface containing the events available.
Instrument developers will need to make available a number of classes and interfaces for plugin developers to provide proper support, such as:
- The instrument-specific interface containing the FMC events (in the case of the WT21, this would be
Wt21FmcEvents
) - The instrument-specific classes used for rendering pages (in the case of the WT21, this would be
Wt21FmcPage
) - Any components which are available to be used for the rendering of the FMC, such as instrument-specific dialog pages, input fields, etc
- The classes which the instrument developer plans to support the extension of (in the case of the WT21, we support extension of
PerfMenuPage
andPerfInitPage
among others)
Adding pages via plugins
It's possible to extend the FMC by creating new pages through a plugin. This can be done through the FmcScreenPluginContext::addPluginPageRoute(route, page, event, defaultProps)
function.
To navigate to these pages, you use the FmcScreen::navigateTo(route, params)
function as you would in an instrument implementation of the FMC.
This function takes the following parameters:
route
[string
]
This string is the route to get to the specified page
page
[FmcPage implementation
]
This parameter takes a class which is extended from the instrument-specific AbstractFmcPage
implementation, and corresponds to the page being displayed.
event
[string | undefined
]
This parameter, when defined, is the event that causes this page to be displayed. If undefined the page must be navigated to another way.
defaultProps
[{[key: string]: any} | undefined
]
This parameter, when defined, contains the default props that will be passed to the page. It can be useful for passing objects from the binder, such as an Fms
object, or a PerformancePlan
object.
Extending pre-existing pages
The FMC framework also provides support for extending and modifying pages which already exist in the FMC. This can be useful for cases such as performance planning, where different aircraft may have different support for performance planning approaches or takeoff - such as in the WT21 where there is no pre-existing support for performance calculations of takeoff or approach, but which is provided in the CJ4 FMC.
Creating the page extension
To extend an already existing FMC page, you need to create a class which extends from AbstractFmcPageExtension
.
This class provides a number of functions to extend behaviour:
onPageRendered
This is the main reason for extending a page - changing the rendering of a page itself. This function contains one parameter, which is the rendered FMC template. From this, you are able to replace or create new entries in the rendered page. An example of how this may be used is as below:
export class PerfMenuPageExtension extends AbstractFmcPageExtension<PerfMenuPage> {
private readonly TakeoffPerfLink = PageLinkField.createLink(this.page, "<TAKEOFF", "/takeoff-ref");
private readonly ApproachPerfLink = PageLinkField.createLink(this.page, "APPROACH>", "/approach-ref");
/** @inheritDoc */
public onPageRendered(renderedTemplates: FmcRenderTemplate[]): void {
renderedTemplates[0][6] = [this.TakeoffPerfLink, this.ApproachPerfLink];
}
}
onPageInit
This function is called when the extended page is initialised. This function is called before the page runs it's onInit function.
onPageResume
This function is called when the extended page is resumed. This function is called after the page runs it's onPause function.
onPagePause
This function is called when the extended page is paused. This function is called after the page runs it's onResume function.
onPageHandleSelectKey
This function is called before the page processes a select key event. If this function returns true
then the select key is considered to have been handled and the page will not process it.
onPageHandleScrolling
This function is called before the page processes a scrolling event. If this function returns true
then the select key is considered to have been handled and the page will not process it.
Registering the page extension
To extend an already existing page, you use the FmcScreenPluginContext::attachPageExtension(pageClass, extension)
function.
For example:
context.attachPageExtension(PerfMenuPage, PerfMenuPageExtension);
The parameters are as follows:
pageClass
[FmcPage implementation
]
This parameter should contain the class of the specific page which is being implemented. For example in the WT21, you might pass PerfMenuPage
.
extension
[class extending AbstractFmcPageExtension
]
This parameter should contain the unconstructed and uninstantiated class which extends AbstractFmcPageExtension
Replacing pre-existing pages
It is possible to entirely replace an existing page route. This can be done through the FmcScreenPluginContext::replacePageRoute(route, page, routeEvent)
function, which takes the following parameters:
route
[string
]
The page route to be replaced.
page
[FmcPage implementation
]
The page which this route should direct to.
routeEvent
[string | undefined
]
The event which will cause this page to be displayed, or undefined where this wouldn't occur.
If you replace a page route which has a defined routeEvent, you will need to also define the routeEvent for the replacement page if you wish to have that event still cause the same page route to be displayed.