This document covers the following topics:
Plug-ins access Natural Studio functionality through an Automation interface. All
individual interfaces that form the Natural Studio Automation interface can be reached
from the root interface, INatAutoStudio. A handle to this interface is
passed to each plug-in during activation and deactivation.
The following tree diagram shows the hierarchical structure of the Automation interface:
INatAutoStudio |_INatAutoObjects |_INatAutoDataAreas |_INatAutoDataArea |_INatAutoDialogs |_INatAutoDialog |_INatAutoPrograms |_INatAutoProgram |_INatAutoGenericDocuments |_INatAutoGenericDocument |_INatAutoGenericTexts |_INatAutoGenericText |_INatAutoObjectLists |_INatAutoObjectList |_INatAutoObjectTrees |_INatAutoObjectTree |_INatAutoObjectTreeNode |_INatAutoSelectedObjects |_INatAutoSelectedObject |_INatAutoRefreshObject |_INatAutoControlBars |_INatAutoImages |_INatAutoCommands |_INatAutoCommand |_INatAutoToolBars |_INatAutoToolBar |_INatAutoFrameMenus |_INatAutoFrameMenu |_INatAutoPopupMenu |_INatAutoContextMenus |_INatAutoContextMenu |_INatAutoPopupMenu |_INatAutoTypes |_INatAutoNodeTypes |_INatAutoNodeType |_INatAutoNodeImages |_INatAutoPlugIns |_INatAutoPlugIn |_INatAutoResultViews |_INatAutoResultView |_INatAutoSystem |_INatAutoEnvironments |_INatAutoEnvironment |_INatAutoNatparm |_INatAutoNatsvar |_INatAutoApplications |_INatAutoApplication |_INatAutoLinkedApplications |_INatAutoEnvironment |_INatAutoSysmain |_INatAutoProgressIndicator
Natural Studio users access plug-in functionality by using commands. A plug-in identifies each command by a number. The number can be freely chosen, but must of course be unique per plug-in. A command can have a caption and an image assigned. Caption and image represent the command in menus and toolbars.
To provide a command to the user, a plug-in first creates an INatAutoCommand interface
in the INatAutoCommands collection:
send "Add" to #commands with 4711 "MyCommand" #myImage return #myCommand
While creating the command, in the above example the plug-in refers to an image
#myImage. This image is used to represent the command visually in menus
and toolbars. The plug-in may have loaded the image before, using the method INatAutoImages::LoadImage:
send "LoadImage" to #images with "e:\images\myimage.bmp" return #myImage
This results in an IPictureDisp interface that can be passed to
the method INatAutoCommands::Add. The
IPictureDisp interface is a predefined interface in Windows. An
IPictureDisp interface can be created in Natural using the
method INatAutoImages::LoadImage.
Alternatively, the plug-in can pass the image file name directly to the method
INatAutoCommands::Add:
send "Add" to #commands with 4711 "MyCommand" "e:\images\myimage.bmp" return #myCommand
When the user later chooses the command in a menu or toolbar, the plug-in is notified
by using the method INaturalStudioPlugIn::OnCommand.
But in order to make the command accessible to users in the first place, the plug-in must insert it into a menu or toolbar. We show this with a toolbar as example. Here the plug-in first locates the Tools toolbar. Then it inserts the previously created command into the toolbar.
send "Item" to #toolbars with "Tools" return #toolsToolbar send "InsertCommand" to #toolsToolbar with #myCommand
The plug-in needs to create the command only once and can then assign it to different toolbars or menus.
The plug-in might as well create its own toolbar and add the command to this toolbar:
send "Add" to #toolbars with "MyToolbar" return #myToolbar send "InsertCommand" to #myToolbar with #myCommand
We saw the plug-in use the interfaces INatAutoCommands, INatAutoImages and
other interfaces. But how does the plug-in get access to these interfaces in the first
place? The plug-in accesses them by querying properties of the root interface, INatAutoStudio. A handle
to this interface is passed to each plug-in during activation and deactivation. From
this interface the plug-in can navigate to any other section of the Natural Studio
Automation interface.
To work with control bars, a plug-in uses the interfaces described in the following sections:
INatAutoControlBars
INatAutoImages
INatAutoCommands
INatAutoCommand
INatAutoToolBars
INatAutoToolBar
INatAutoContextMenus
INatAutoContextMenu
INatAutoFrameMenus
INatAutoFrameMenu
INatAutoPopupMenu
Natural Studio frequently uses tree views and list views to display development objects and to navigate through them. Each node in a tree view or list view is characterized by a node type. The node type defines how nodes of a given type are represented in the user interface.
Each node type is identified by an integer number. A development object belonging to a given node type is identified by the number of that node type and by an alphanumeric key. The format of the key varies from node type to node type.
Plug-ins that wish to create their own tree views and list views in Natural Studio can refer to the predefined node types. In addition, plug-ins can define their own node types and can then refer to these user-defined node types.
The following topics are covered below:
The built-in Natural Studio development objects such as program, dialog, class, library or application have a predefined node type and key format. Many interfaces and methods in the Natural Studio Automation interface refer to the predefined node types. The full list of available predefined node types and the format of their keys is defined in the following tables.
| Node Type Number | Node Type Name | Key Format |
|---|---|---|
| 1001 | Parameter data area | NATID |
| 1002 | Copycode | NATID |
| 1003 | DDM | NATID |
| 1004 | Global data area | NATID |
| 1005 | Helproutine | NATID |
| 1006 | Local data area | NATID |
| 1007 | Map | NATID |
| 1008 | Subprogram | NATID |
| 1009 | Program | NATID |
| 1010 | Subroutine | NATID |
| 1011 | Text | NATID |
| 1012 | View | NATID |
| 1013 | Dialog | NATID |
| 1014 | Class | NATID |
| 1015 | Command processor | NATID |
| 1017 | Mainframe DDM | DDMID |
| 1018 | Function | NATID |
| 1019 | Shared resource | RESID |
| 1020 | Error message file | NATID |
| 1021 | Adapter | NATID |
| 1051 | Parameter data area (in application) | NATID |
| 1052 | Copycode (in application) | NATID |
| 1053 | DDM (in application) | NATID |
| 1054 | Global data area (in application) | NATID |
| 1055 | Helproutine (in application) | NATID |
| 1056 | Local data area (in application) | NATID |
| 1057 | Map (in application) | NATID |
| 1058 | Subprogram (in application) | NATID |
| 1059 | Program (in application) | NATID |
| 1060 | Subroutine (in application) | NATID |
| 1061 | Text (in application) | NATID |
| 1062 | View (in application) | NATID |
| 1063 | Dialog (in application) | NATID |
| 1064 | Class (in application) | NATID |
| 1065 | Command processor (in application) | NATID |
| 1067 | Mainframe DDM (in application) | DDMID |
| 1068 | Function (in application) | NATID |
| 1069 | Shared resource (in application) | RESID |
| 1070 | Error message file (in application) | NATID |
| 1071 | Adapter (in application) | NATID |
| 1101 | System file | FILEID |
| 1102 | Natural system file | FILEID |
| 1103 | User system file | FILEID |
| 1104 | DDM system file | FILEID |
| 1111 | Library | LIBID |
| 1112 | Library (in application) | LIBID |
| 1121 | Environment | BSTR |
| 1131 | Base application | BSTR |
| 1132 | Compound application | BSTR |
| 1141 | Application server | BSTR |
| Syntax | Description |
|---|---|
| name library fnr dbnr | Identifies the Natural development object with the given name in the given library in the given system file. The individual parts of the identifier are separated by spaces. |
| name library | Identifies the Natural object with the given name in the given library. The system file is then determined from the library according to the usual Natural logic, depending on the library name. The individual parts of the identifier are separated by spaces. |
| name | Identifies the Natural object with the given name in the current logon library. |
| Syntax | Description |
|---|---|
| name/library/fnr/dbnr | Identifies the shared resource with the given name in the given library in the given system file. The individual parts of the identifier are separated by slashes. |
| name/library | Identifies the shared resource with the given name in the given library. The system file is then determined from the library according to the usual Natural logic, depending on the library name. The individual parts of the identifier are separated by slashes. |
| name | Identifies the shared resource with the given name in the current logon library. |
| Syntax | Description |
|---|---|
| name fnr dbnr | Identifies the mainframe DDM with the given name in the
given FDIC system file. The individual parts of the identifier
are separated by spaces.
|
| name | Identifies the mainframe DDM with the given name in the
current FDIC system file.
|
| Syntax | Description |
|---|---|
| name fnr dbnr | Identifies the Natural library with the given name in the given system file. The individual parts of the identifier are separated by spaces. |
| name | Identifies the Natural library with the given name. The system file is then determined from the library according to the usual Natural logic, depending on the library name. |
| Syntax | Description |
|---|---|
| fnr dbnr | Identifies the Natural system file with the given numbers. The individual parts of the identifier are separated by spaces. |
Assume that in a certain development environment, we have a system file with the
database number "101" and the file number
"99", containing a library MYLIB with a
program MYPROG.
In the given environment
the program is identified by the node type 1009 and the key "MYPROG MYLIB 99 101",
the library is identified by the node type 1111 and the key "MYLIB 99 101",
the system file is identified by the node type 1103 and the key "99 101".
Plug-ins can define their own node types. This is useful if a plug-in wants to display tree views or list views of development objects not belonging to the predefined set of Natural Studio objects. An example is the Object Description plug-in. It is also useful for plug-ins that want to display certain aspects of Natural Studio objects not covered by built-in Natural Studio functionality. An example is the XRef Evaluation plug-in.
When defining its own node type, a plug-in is free to choose an arbitrary positive integer value starting with "20000". Values below "20000" are reserved for predefined node types. It does not matter if different plug-ins chose the same integer value for a node type. Internally, Natural Studio distinguishes the node types by their numbers and by the plug-in that defined the node type.
The plug-in is free to define the key format for each user-defined node type. Natural Studio does not interpret the keys of user-defined node types, but treats them as opaque strings.
To define new node types and their visual representations, a plug-in uses the interfaces described in the following sections:
INatAutoTypes
INatAutoNodeImages
INatAutoNodeTypes
INatAutoNodeType
Through the interfaces described in this section, plug-ins can access the set of objects the user has currently selected in Natural Studio. A plug-in might need this information to decide if a specific menu or toolbar command is applicable to the current selection and must hence be enabled in the user interface. If the user then executes the command, the plug-in again needs to know the set of selected objects in order to apply the command to each of them. A plug-in has access to the current selection through the interfaces described in this section.
In order to work with the current selection, a plug-in starts with the root interface
INatAutoStudio,
retrieves the INatAutoObjects interface and then the INatAutoSelectedObjects interface. We assume here
that the plug-in has kept a handle to the interface
INatAutoStudio in a variable named #studio. This
handle was passed to the plug-in during activation, in the method INaturalStudioPlugIn::OnActivate.
#objs := #studio.Objects #selobjs := #objs.SelectedObjects
The returned INatAutoSelectedObjects interface gives access to
the set of objects the user has currently selected. Using this interface, the plug-in
can, for instance, iterate across the selected objects and inspect them. The method
Item returns an INatAutoSelectedObject interface to a specific
selected object.
#iCount := #selobjs.Count for #i := 1 to #iCount send "Item" to #selobjs with #i return #selobj #iType := #selobj.Type #aKey := #selobj.Key end-for
The property FocusObject returns the index of the specific
selected object that currently has the focus. This index can be used to retrieve the
INatAutoSelectedObject interface of the focus
object.
#iFocus := #selobjs.FocusObject send "Item" to #selobjs with #iFocus return #focus
The method ContainsObjectType can be used for a quick check if
the current selected set contains objects of a specific type. This might be sometimes
sufficient to decide if a specific command shall be enabled or not.
send "ContainsObjectType" to #selobjs with 1009 return #bContainsPrograms
For specific checks the plug-in can also retrieve and process the current selection as an XML document.
#aSelectedObjectsXML := #selobjs.SelectedObjects
To work with selections, a plug-in uses the interfaces described in the following sections:
INatAutoObjects
INatAutoSelectedObjects
INatAutoSelectedObject
Through the interfaces described in this section, plug-ins can create and edit Natural development objects. Being able to create new development objects, load existing objects into an editor, manipulate their contents and to save and stow them, enables plug-ins to provide generation functions and thus to help automating the development process. An example is the Program Generation plug-in.
To open a program in the program editor, for instance, a plug-in starts with the root
interface INatAutoStudio, retrieves the INatAutoObjects interface
and then the INatAutoPrograms interface. Now it uses the
method INatAutoPrograms::Open to load the program into
the editor.
We assume here that the plug-in has kept a handle to the interface
INatAutoStudio in a variable named #studio. This
handle was passed to the plug-in during activation, in the method INaturalStudioPlugIn::OnActivate.
#objects := #studio.Objects #programs := #objects.Programs send "Open" to #programs with 1009 "MYPGM" "MYLIB" return #program
The resulting INatAutoProgram interface can now be used to
operate on the program, for instance, to stow it and then to close the editor.
send "Stow" to #program send "Close" to #program
A new program source is created by using the method Add.
send "Add" to #programs with 1009 return #program
Source code is added to the program either as a whole by using the property Source:
#program.Source := "WRITE ""HELLO, WORLD!"" END
Or incrementally by using the method InsertLines.
send "InsertLines" to #program with "WRITE ""HELLO, WORLD!" #return #next send "InsertLines" to #program with "END" #next return #next
The interface INatAutoProgram provides also search and replace
methods and other methods to modify the source code.
send "Search" to #program with "HELLO" return #found send "ReplaceLines" to #program with "WRITE ""Good morning" #found
Dialogs and data areas are accessed in a similar way by using the interfaces INatAutoDialog and
INatAutoDataArea. But there is one particularity
with these objects: Even though there is a graphical or structured editor in the user
interface for these objects, they are edited textually through the Automation interface.
Applied to data areas this means: If a plug-in wants to generate a data area, it
actually has to generate a DEFINE
DATA statement.
#objects := #studio.Objects #dataareas := #objects.DataAreas send "Add" to #dataareas with 1006 return #lda * send "StartEdit" to #lda send "InsertLines" to #lda with "DEFINE DATA LOCAL" return #next send "InsertLines" to #lda with "1 MYSTRING(A10)" #next return #next send "InsertLines" to #lda with "1 MYNUMBER(I4)" #next return #next send "InsertLines" to #lda with "END-DEFINE" #next return #next send "EndEdit" to #lda * send "Stow" to #lda send "Close" to #lda
The calls to the methods INatAutoDataArea::StartEdit and INatAutoDataArea::EndEdit are used to mark the
beginning and end of a series of editing operations.
To work with Natural development objects, a plug-in uses the interfaces described in the following sections:
INatAutoObjects
INatAutoPrograms
INatAutoProgram
INatAutoDialogs
INatAutoDialog
INatAutoDataAreas
INatAutoDataArea
Through the interfaces described in this section, plug-ins can use the Natural Studio program editor as editor for arbitrary text objects. A plug-in can open a program editor session, pass a buffer with text data to it, let the user edit the data and then retrieve the modified data back. The plug-in itself is responsible for providing and storing the data to be edited. The program editor provides the usual editing functions, as far as they are appropriate for generic text objects.
To let the user edit a given text in the program editor, a plug-in starts with the root
interface INatAutoStudio, retrieves the INatAutoObjects interface
and then the INatAutoGenericTexts interface. Now it uses the
method INatAutoGenericTexts::Open to load the text
buffer into the editor.
We assume here that the plug-in has kept a handle to the interface
INatAutoStudio in a variable named #studio. This
handle was passed to the plug-in during activation, in the method INaturalStudioPlugIn::OnActivate. Also we
assume that the text to be edited is contained in the alphanumeric variable
#buffer.
#objects := #studio.Objects #texts := #objects.GenericTexts send "Open" to #texts with "Curriculum Vitae" "Dana Scully" #buffer return #text
The editor is then opened and the user can edit the text interactively.
The plug-in can use the resulting INatAutoGenericText interface to operate on the
text, for instance, to insert lines:
send "InsertLines" to #text with "Taught for two years at Quantico Medical School"
If the user chooses the button in the editor, the plug-in
receives the notification PLUGIN-NOTIFY-SAVE. In response to this notification, it
will usually retrieve the edited text from the editor and save it.
#buffer := #text.Source * Now save the text in a plug-in specific way.
To work with generic text documents, a plug-in uses the interfaces described in the following sections:
INatAutoGenericTexts
INatAutoGenericText
INatAutoObjects
A plug-in that maintains own development objects might want to provide its own editors for each of its development object types. Editors in Natural Studio typically maintain development objects in MDI (Multiple Document Interface) windows. In the following, we call them document windows. Natural Studio has a number of built-in editors, for instance, the program editor and the dialog editor. A plug-in can implement its own editor with a so-called generic document window.
Implementing such an editor as a generic document window makes the editor behave like the built-in editors in Natural Studio. Essentially this means: Several editor windows on different objects can be opened in parallel and the user can switch between them.
In order to implement a generic document window, you first create a Natural dialog of
type "Plug-in MDI window". In your plug-in code, you can then open this
dialog with the OPEN DIALOG
statement and let Natural Studio display the dialog as a document window. Normally you
will do this in the command handler of your plug-in, that is in the method INaturalStudioPlugIn::OnCommand:
open dialog "mydlg" null-handle giving #dialogid #objects := #studio.Objects #genericdocs := #objects.GenericDocuments send "Add" to #genericdocs with #dialogid return #doc
The resulting INatAutoGenericDocument interface can now be used
to operate on the document window.
The plug-in has several other means to communicate with the Natural dialog contained in the generic document window:
The plug-in can send events to the dialog with the SEND EVENT statement and using
the dialog ID.
The dialog can send method calls to the plug-in. To achieve this, the plug-in
should pass its own *THIS-OBJECT handle to the dialog in the OPEN DIALOG statement.
The dialog can call the Natural Studio Automation interface. To achieve this, the
plug-in should pass the INatAutoStudio interface pointer to the
dialog in the OPEN DIALOG
statement.
Whenever the user activates a document window, Natural Studio automatically switches the frame menu to a menu that contains the commands applicable to the active document. In the case of built-in document windows, these frame menus are predefined. In the case of a generic document window, the plug-in itself can provide an appropriate frame menu.
The plug-in can create a frame menu of its own by cloning an existing frame menu using
the method INatAutoFrameMenus::Clone and adding new
commands to the clone as necessary using the method INatAutoFrameMenu::InsertCommand.
Afterwards it passes the resulting INatAutoFrameMenu interface to Natural Studio
when calling the method INatAutoGenericDocuments::Add.
To work with generic documents, a plug-in uses the interfaces described in the following sections:
INatAutoGenericDocuments
INatAutoGenericDocument
INatAutoObjects
Through the interfaces described in this section, a plug-in can display its own tree views and list views in Natural Studio. Tree views and list views are frequently used in Natural Studio to display development objects and to navigate through them.
In order to display objects in tree views and list views, the plug-in must first register the types of the tree or list view nodes that it is going to display. This procedure is described in Working with Node Types.
A plug-in that displays objects in tree views and list views must also implement the
methods of the interface INaturalStudioPlugInTree appropriately. Natural
Studio calls the methods of this interface when expanding or refreshing the tree.
In order to open a tree view, the plug-in starts with the root interface INatAutoStudio, retrieves
the INatAutoObjects interface and then the INatAutoObjectTrees
interface. We assume here that the plug-in has kept a handle to the interface
INatAutoStudio in a variable named #studio. This
handle was passed to the plug-in during activation, in the method INaturalStudioPlugIn::OnActivate.
#objs := #studio.Objects #trees := #objs.ObjectTrees
The resulting INatAutoObjectTrees interface gives access to the
currently open tree view document windows. Through this interface the plug-in can open a
new tree view with a given root object.
send "Open" to #trees with #type #key #caption return #tree
The node type specified in the method Open must have been registered before, as
described in Working with Node
Types. The INatAutoObjectTree interface returned from the
method Open gives access to the tree view document window just
opened. Through this interface the plug-in can, for instance, later close the document
window.
send "Close" to #tree
When opening a tree view, the plug-in specifies at least the type and key of the root
object and a caption to be displayed on the tree view document window. Natural Studio
will retrieve additional information needed to expand the tree view by using the
interface INaturalStudioPlugInTree that must be implemented
by the plug-in.
The nodes of a tree view can be accessed through the interface INatAutoObjectTreeNode. The root node of a tree
view is retrieved with the method INatAutoObjectTree::GetRootNode, which returns
an interface INatAutoObjectTreeNode. This interface can then be
used, for instance, to expand the node and to access the child nodes. In the same way,
the currently selected node of a tree view can be retrieved.
send "GetRootNode" to #tree return #rootnode send "Expand" to #rootnode send "GetChild" to #rootnode return #firstchildnode send "GetNext" to #firstchildnode return #nextchildnode send "Expand" to #nextchildnode send "GetSelectedNode" to #tree return #selectednode send "Expand" to #selectednode
The interface INatAutoObjectTreeNode controls only the visual
appearance of an individual tree view, not the underlying object structure, which is
possibly represented differently in several views at a time. The object structure itself
is under the control of the plug-in that defines and provides it through its INaturalStudioPlugInTree interface.
List view document windows are created in a similar way as tree view document windows,
except that the interface INatAutoObjectLists is used instead of INatAutoObjectTrees.
To work with tree views and list views, a plug-in uses the interfaces described in the following sections:
INatAutoObjects
INatAutoObjectTrees
INatAutoObjectTree
INatAutoObjectTreeNode
INatAutoObjectLists
INatAutoObjectList
INatAutoRefreshObject
Through the interfaces described in this section, a plug-in can display the results of its work in the Natural Studio result view. Objects displayed in a result view can be target of commands and can be used as starting point for navigation. Examples of built-in functions that use result views are the command and the command.
In order to display objects in result views, the plug-in must first register the types of nodes that it is going to display. This procedure is described in the section Working with Node Types.
In order to work with result views, the plug-in starts with the root interface
INatAutoStudio
and retrieves the INatAutoResultViews interface. We assume here
that the plug-in has kept a handle to the interface
INatAutoStudio in a variable named #studio. This
handle was passed to the plug-in during activation, in the method INaturalStudioPlugIn::OnActivate.
#resultviews := #studio.ResultViews
The resulting INatAutoResultViews interface gives access to the
result view control bar and the currently open result views. The plug-in can use this
interface, for instance, to show or hide the result view control bar.
send "Show" to #resultviews
Through the interface INatAutoResultViews the plug-in can open a
new result view.
send "Open" to #resultviews with #caption #image #headers return #resultview
When opening a result view, the plug-in specifies a caption and an image to be displayed on the result view tab and (if needed) column headers for the result view.
The INatAutoResultView interface returned from the
method Open gives access to the result view just opened.
Through this interface the plug-in can activate the result view, insert rows into it and
update the display. The method SetVisible scrolls a specific row into
view.
#resultview.Active := true send "InsertRows" to #resultview with #rows return #last send "Update" to #resultview send "SetVisible" to #resultview with #last
Finally the plug-in can close its result view.
send "Close" to #resultview
To work with result views, a plug-in uses the interfaces described in the following sections:
INatAutoResultViews
INatAutoResultView
Through the interfaces described in this section, plug-ins can inspect the available local and remote development environments, map environments, connect to and disconnect from a remote environment and activate an environment.
In order to work with environments, a plug-in starts with the root interface INatAutoStudio, retrieves
the INatAutoSystem
interface and then the INatAutoEnvironments interface. We assume here
that the plug-in has kept a handle to the interface
INatAutoStudio in a variable named #studio. This
handle was passed to the plug-in during activation, in the method INaturalStudioPlugIn::OnActivate.
#system := #studio.System #envs := #system.Environments
The returned INatAutoEnvironments interface gives access to
the local environment and all remote environments that have once been connected during
the current Natural Studio session.
Through this interface the plug-in can, for instance, map a new remote environment, specifying host name, port number, user ID, password and other arguments.
send "Add" to #envs with "IBM2" "4712" "SCULLY" "secret" "STACK=(LOGON XFILES)" return #env
The returned interface INatAutoEnvironment gives access to attributes of
the environment.
#bIsActive := #env.Active #bIsConnected := #env.Connected
The property Parameters gives access to the interface
INatAutoNatparm. This interface contains properties
that represent the Natural parameters under which the environment is running. Only a
subset of the Natural parameters is available through this interface.
#natparm := #env.Parameters #fuserDBnr := #natparm.FuserDBnr #fuserFnr := #natparm.FuserFnr
The property SystemVariables gives access to the
interface INatAutoNatsvar. This interface contains properties
that represent the system variables currently set in the environment. Only a subset of
the system variables is available through this interface.
#natsvar := #env.SystemVariables #language := #natsvar.Language
The plug-in uses the method Disconnect to disconnect from the remote
environment.
send "Disconnect" to #env
To work with environments, a plug-in uses the interfaces described in the following sections:
INatAutoEnvironments
INatAutoEnvironment
INatAutoSystem
INatAutoNatparm
INatAutoNatsvar
Through the interfaces described in this section, plug-ins can inspect the applications available on the application server, map applications into the Natural Studio session, connect to and disconnect from an application, activate an application and create and modify applications. An example of a plug-in that uses this section of the interface is the Application Wizard.
In order to work with applications, the plug-in starts with the root interface
INatAutoStudio,
retrieves the INatAutoSystem interface and then the INatAutoApplications
interface. We assume here that the plug-in has kept a handle to the interface
INatAutoStudio in a variable named #studio. This
handle was passed to the plug-in during activation, in the method INaturalStudioPlugIn::OnActivate.
#system := #studio.System #apps := #system.Applications
The resulting INatAutoApplications interface gives access to
the currently active application server and the applications it contains. Through this
interface the plug-in can, for instance, ask for the currently active application.
#app := #apps.ActiveApplication
The plug-in can also create a new application and map it into the Natural Studio session.
send "Add" to #apps with "MYAPPLICATION" return #app
The resulting INatAutoApplication interface gives access to
attributes of the application.
#bIsActive := #app.Active #bIsConnected := #app.Connected
For a compound application, the property LinkedApplications returns the interface
INatAutoLinkedApplications. This interface allows
accessing the base applications that are linked to the compound application.
#linkedapps:= #app.LinkedApplications #iCount := #linkedapps.Count
For a base application, the property LinkedObjects returns an XML document
containing the list of objects linked to the application.
#aObjects:= #app.LinkedObjects
The plug-in can also link and unlink objects to and from the application.
send "UnlinkObject" to #app with 1009 "OLDPROG" "MYLIB" send "LinkObject" to #app with 1009 "NEWPROG" "MYLIB"
Finally the plug-in can disconnect and unmap the application.
send "Disconnect" to #app send "Unmap" to #app
To work with applications, a plug-in uses the interfaces described in the following sections:
INatAutoApplications
INatAutoApplication
INatAutoLinkedApplications
Through the interfaces described in this section, a plug-in can inspect the currently installed plug-ins, read their properties and activate or deactivate a plug-in. This includes the possibility that a plug-in deactivates itself. An example for a plug-in that uses this section of the interface is the Plug-in Manager.
In order to work with plug-ins, the plug-in starts with the root interface INatAutoStudio and
retrieves the interface INatAutoPlugIns. We assume here that the plug-in
has kept a handle to the interface INatAutoStudio in a variable
named #studio. This handle was passed to the plug-in during activation, in
the method INaturalStudioPlugIn::OnActivate.
#plugins := #studio.PlugIns
The resulting INatAutoPlugIns interface gives access to the
currently installed plug-ins. Using this interface, the plug-in can, for instance,
iterate across the installed plug-ins and inspect their attributes. The method Item returns an
INatAutoPlugIn
interface to a specific plug-in.
#iCount := #plugins.Count for #i := 1 to #iCount send "Item" to #plugins with #i return #plugin #aName := #plugin.Name #aProgID := #plugin.ProgID #bIsActive := #plugin.Active end-for
Through the interface INatAutoPlugIn the plug-in can also activate or
deactivate a specific plug-in by modifying the property Active. The
following sample toggles the activation state of a plug-in.
#bIsActive := #plugin.Active if #bIsActive #plugin.Active := false else #plugin.Active := true end-if
The interface INatAutoPlugIn can be used to send a command to the
plug-in. The following sample checks whether the plug-in command with the ID
"200" is currently enabled and if so, lets the plug-in
execute the command. Of course this requires that we know that the plug-in implements a
command with the ID "200" and what this command does.
#bEnabled = false #bChecked := false send "OnCommandStatus" to #plugin with 200 #bEnabled #bChecked if #bEnabled send "OnCommand" to #plugin with 200 end-if
Through the interface INatAutoPlugIn, the plug-in can get access to
arbitrary services that another plug-in provides with a so-called custom interface. The
following sample retrieves the custom interface of a plug-in and calls one of its
services. Of course this requires that the plug-in has documented the services it
provides with its custom interface.
#icustom := null-handle send "GetCustomInterface" to #plugin return #icustom if #icustom ne null-handle #result := 0 send "GetMaritalStatus" to #icustom with "Anderson, Gillian" return #result end-if
In order to provide a custom interface, a plug-in must implement an additional
interface beside the two predefined interfaces INaturalStudioPlugIn and INaturalStudioPlugInTree and make this interface
the default dispatch interface. For a plug-in implemented in Natural this means placing
this interface at the first position in the DEFINE CLASS statement.
define class ...
object using ...
id "..."
interface icustom
id "..."
method GetMaritalStatus id 1 is gstat-n
parameter using gstat-a
end-method
end-interface
interface using nstplg-i
interface using nstplt-i
end-class
end
To work with plug-ins, a plug-in uses the interfaces described in the following sections:
INatAutoPlugIns
INatAutoPlugIn
If a plug-in wants to open dialog boxes in Natural Studio, some special considerations have to be taken. The support of dialog boxes in plug-ins depends mainly on the condition if the plug-in is running in as an in-process ActiveX component or if it is running in a separate process.
The following topics are covered below:
In general, an ActiveX component running in a separate process cannot open a dialog box in the client process. This restriction of the Windows system itself is overcome in the special case that a plug-in is written in Natural.
If a plug-in is written in Natural, it can open modal dialog boxes in Natural Studio. Precisely this means: Natural dialogs that are defined in the dialog editor with the Type attribute set to "Standard window" and the Style attribute set to "Dialog box". Other styles of the dialog type "Standard window" cannot be used in plug-ins.
To open a dialog box, a plug-in uses the usual OPEN DIALOG statement.
If a plug-in is implemented as an in-process ActiveX component (this means: as a DLL), it can open modal and non-modal dialogs in Natural Studio. To open a dialog, the plug-in uses the statements usual in the programming language it is written in. Plug-ins written in Natural always run in a separate process, so this applies only to plug-ins written in programming languages that support implementing in-process ActiveX components.
For details on how to implement plug-ins in programming languages other than Natural, see Developing Plug-ins in Other Programming Languages.