Copyright (c) Prolog
Developemnt Center SPb
Application Frame. Plugin mechanism
The plugins mechanism in
ApplicationFrame is based on the concept of PzlSystem, which is a
system of conventions for using DLLs to store part of an executable
system.
The PzlSystem concept is
described in more detail in the VpPuzzle document .
System packages are located
in the SpbVipTools\Packs\Logic\PzlSystem\OpenPzl directory.
Each of the
AppFrame project variants in accordance with the concept of
VpPuzzle is a pzl-Container, that is, it can contain pzl-Components. The AppFrame core
does not use the properties of the pzl-Container, however, nothing
prevents a particular project from using these properties.
The Plugins mechanism
involves the use of the pzl-Component located in pzl-Containers, each
of which is a DLL. Each pzl-Container may
contain any number of pzl-Components.
Pzl-Components, the use of
which is supposed to be in a project based on AppFrame, must be
pre-registered by any of the methods provided by the pzl-Concept.
Each pzl-component can
refer to any other registered pzl-components. The depth of the call
hierarchy is unlimited.
However, the
AppFrame only "knows" about the component it is accessing.
Call plugin
Since the AppFrame
architecture assumes strict separation of FrontEnd and BackEnd, Plugins
calls in the context of FrontEnd and BackEnd have their own
characteristics.
In particular, this
concerns the invocation of a component represented by its user
interface, a command from the control panel.
In the xml description of
the control panel for the AppFrame core, the agreement
on the key combination
ribbon.cmd.plugin.
<Component name>
and
the data for the category property
of the command in the command identifier
is significant. Moreover, the content of the category property
data is determined only by the
plugin component developer.
An example pzl call
definition of pzlGame Components is given
below
<cmd
id="ribbon.cmd.plugin.pzlGame"
label="Game_PLL14"
cmdstyle="image-and-text-vertical"
run="pzl-extension"
menu-label="Game_PLL14"
enabled="true"
visible="true"
category=""
>
<icon
file="$(pdc-external)\categories\applications-games.ico"/>
<tooltip text="Polyline14 aggregated
pzlComponent"/>
</cmd>
Here is the category property shown
for completeness, although it might be absent, since it has no
practical value.
The definition of the run = "pzl-extension" attribute
is important , which means that pzl-extension is
the identifier of the predicate that will be called when the command
with label = "Game_PLL14" is
activated .
When determining the
context for this case, the assignment must be
setCommonPerformers(ContextObj):-
...
ContextObj:setRunner("pzl-extention",fe_CoreTests():runPlugin),
...
And
in the object fe_CoreTests() call of the pzl-Component
may look like this:
clauses
runPlugin ( Command ): -
PluginID = fe_Command :: tryExtractCommandSuffix ( Command , "ribbon.cmd.plugin." ),
!,
ComponentObj = pzl :: newByName ( PluginID , fe_AppWindow ()),
Component = convert ( pzlRun , ComponentObj ),
Component : pzlRun ( toString (Command : category )).
runPlugin ( Command ): -
Msg = string :: format ( "Not pzl plugin invocation
command [%] \ n " , Command : id ),
log :: write ( log :: error , Msg ),
exception :: raise_User ( Msg )
It uses the convention that
components represented by the user interface can be invoked
by calling the predicate pzlRun
(...) with
the transfer to him of the necessary data in text form. This example passes the
contents of the category property
of the command. The pzlRun interface (containing the predicate
of the same name) is one of the interfaces of the pzl-System.
After calling the pzlRun
predicate, the further behavior of Plugin is determined by its
implementation. After the plugin completes,
all its components will be automatically unloaded and the memory will
be freed (when garbageCollector will run).