[PREVIOUS] [NEXT] [UP

Reuseable Tools

This chapter provides some hints how to implement reuseable tools with Neo/NST. The examples mainly illustrate various possibilities how a tool can "export" its operations in a way that is as convenient as possible for re-use.

Tools that work on data: customized plain units

Simple tools may just take the form of standard units, specialized to a frequently occurring task and equipped with a suitable dialog window for that purpose. A particularly wide range of possibilities is offered by the prog_unit which - with a suitable program text - can implement almost any operation. The program text that appears in the standard prog_unit creation dialog window can then be "hidden" by specifying (as explained in the chapter Encapsulation) a suitable customized creation dialog window that selectively queries the key parameters of the program (which are then referenced as local @i variables in the underlying program text).

Example#1 shows a prog_unit to "convert" a dynamic input vector connector into a fixed dimension connector. The fixed dimension connector is treated like a "window" (of a fixed number of elements) into the dynamic input vector, starting at an element index given by the value of the second input connector. If the fixed dimension extends beyond the dynamic vector, the remaining element positions are padded with zeroes. The left instance is a prog_unit that implements the described function. The right instance is a copy of the left instance, but equipped with a user-defined creation-dialog window that "hides" the prog_unit code and instead offers a dialog for setting the only user-relevant parameter, that is, the dimension of the fixed-dimension output connector that is used as a window into the dynamic-dimension input.

Examples of more sophisticated "plain" units for various data transformations are provided by the "data mining units" in folders Dm_IO, Dm_trafo, Dm_model and Dm_stats.
 

Tools that work on operands: operator units

In more complex cases, the "input" cannot be restricted to only data fed to input connectors, but more generally, it consists of one or several other NST units. An example, e.g., is a tool that samples a given function (implemented as a NST unit) on a two-dimensional data grid and collects the results in an output connector. In this case, the input would consist of a data part (specifying the data grid points) and an operand (the to-be-sampled function, implemented as a NST circuit). Tools of this more general kind can be implemented in the form of operator units that - similar to the for_op or if_op units - take one or several NST units as operands that they execute to achieve their task. Before, between and after execution of the operand(s), the operator unit may additionally exchange data with the interface of the operand(s), either through wires (which then must have been inserted by the user of the tool), or directly, e.g., when the operand is referenced through a virtual_unit.

Operator units can be implemented either with the prog_unit (using the built-in exec_opnds() function that turns the prog_unit (or method units of it) into a for_op-like operator unit), or with the virtual_unit or virtual_for_op unit embedded into a container. In this case, the entire container is turned into an operator unit.

Example#2 illustrates the technique with an operator unit grid_op that expects a single operand and samples it at the points of a rectangular, uniformly spaced data grid whose extent is specified in the creation dialog window of the operator unit. The sampled values are collected at output connector out_0 (actually, a more general version of this example circuit is provided as a compiled unit under the name spatial_operator).

The circuit also contains three example units prog0, prog1 and prog2, each of which implements a different function. Shifting one of these into the operand position of the operator unit and executing the latter will do the sampling. The sampled values can then be displayed by subsequently executing the write_pix unit that is attached to the result connector of the grid_op unit.

Example#3 is a more elaborate version which now not only samples the operand but in addition forms from the sampled data a contour plot that is displayed in a plot_xy window that is used by the operator unit, now labelled contour_op. In this case, the window reference (appearing in the clear_window and iso_contour units inside the contour_op) is not a window name, but a relative position (-1) that indicates that the first predecessor window (whatever its name) of the window referencing unit shall be used. This way of referencing windows by a relative position index can be occasionally convenient to avoid the need for specifying window names; of course, the "-1" could also be replaced by a proper window name everywhere (then the plot_xy window must bear that name). In addition, there are again three example units, prog0, prog1 and prog2, implementing three different test functions. You can display a contour plot of each of these functions by just shifting the appropriate unit into the successor (= operand) position behind the contour_op tool unit and executing the latter with "x".

Tools that draw into graphics windows

A further possibility is that the tool draws something into into an existing window. For instance, we might make the previous contour drawing operator more general by not tying it to its own, fixed window but instead just providing a creation dialog parameter that specifies the name or a relative position index (negative to choose a predecessor window, positive to choose a successor window) of a plot window into which to deliver the drawing. This would then allow to combine the output of this tool with other graphics in an already existing window.

Tools to provide an interaction mechanism

Yet another possibility is that the tool provides some interaction mechanism with an existing window (specified by its name in the creation dialog of the tool). Usually, a tool of this kind will consist of one (or several) mouse_xy instances that become bound to the specified window and that invoke suitable callback units to implement the intended interaction.

Example#4 shows a unit named rect_mouse that offers the capability to trace out a rectangle (e.g. for selecting a region) in a named window. The "behavior" of the tool is like that of the mouse_xy unit, but with the additional property of rectangle tracing. When the unit returns, its four output pins will contain the coordinates of two diagonally opposite corners of the traced rectangle (note that the implementation of this function has become tremendously simplified by the use of the newly introduced mouse callbacks together with a prog_unit that implements three method subunits bgn_rect, size_rect and end_rect for being called by the mouse during the different phases of the rectangle tracing; compare with the "old-style-implementation" of the same functionality in the data mining plot2d unit!).

Tools with callbacks as parameters

When a tool becomes more complex, a further important possibility to "couple" the tool with its usage-environment is the use of named callbacks. This can be more flexible than (positionally coded) operand units. An example is an editor tool that implements the necessary mouse interaction to create, move or destroy a variable number of marker symbols in a 2d-coordinate system. To each created marker point, we may wish to specify an attribute vector of further, application dependent parameters.

Example#5 illustrates, how such a tool might be implemented. The basic circuit follows the scheme explained in chapter
Interactive programs to make a graph editor, but (for simplicity) with the part that implements the insertion or deletion of links omitted. In contrast to the graph editor example, the entire editor is now implemented as an encapsulated unit named edit1, without its own window and working instead on an external window whose name must be specified as the first parameter in the creation dialog. Additionally, the tool has a 4-pin input connector that is used to specify the mode of the edit operation (numerical entries 2,3,4,8 in components 0,1,2,3 specify addition, moving, deletion of a marker point, or clearing all markers). A further input parameter is the name of a callback unit that will be called whenever a marker point is created. The assumption is that the callback unit has at least an output connector in position 0 of the same dimension as the attribute vector to provide a set of attribute values for each added marker point. The first three attributes are always color, symbol type and size and the current callback unit is just a simple const_vec (named attri) to provide three constant values (you can change them between invocations of the input_window unit to add marker points of different color, shape and size).

Example#6 illustrates how several instances of such a tool can be used simultaneously and on different or even the same window(s).

Tools parametrized with shared libraries

As a last and very powerful mechanism we mention the use of shared libraries as tool parameters. The prog_unit allows the #import of functions and/or objects implemented in C/C++ in shared libraries (the implementation of such functions/objects is explained here). Since both the argument of an #import directive and the name of a function call can take the form of a local variable @i (holding the required textual identifier), the imported libraries and/or functions/objects can be controlled with parameters in the dialog window of a suitably customized prog_unit. This allows to implement tools with operations that can be changed at a very high level of abstraction, provided the interfaces of the used functions can be kept constant.

[PREVIOUS] [NEXT] [UP]