Sysquake Pro – Table of Contents
Sysquake for LaTeX – Table of Contents
SQ Files Reference (Advanced Features)
This section describes the more advanced features of SQ files.
Dragin and Dragout Handlers
The dragin and dragout handlers are used for drag operations between different figures. A dragin handler must be defined in the scope of the figure which can be the target of cross-figure drag operations, and a dragout handler must be defined in the scope of the figure from where cross-figure drag operations are initiated.
No dragin or dragout is called unless a drag operation starts from a figure which has a dragout handler (source) and the mouse is moved over a figure which has a dragin handler (target). In that case, when the mouse enters the target figure, the source dragout handler is called first, then the target dragin handler. Then the dragging continues exactly as if it had started from the target figure, with calls to the mousedrag, mousedragcont, and/or mouseup handlers of the target figure. Other cross-figure drag operations can follow if the first target figure has a dragout handler.
Here is the sequence of calls during a drag, extended to take into account one or several drags between figures.
Sw = S0 Sw = mousedown_i(Sw) Sw = draw_i(Sw) S1 = Sw while the mouse is down while the mouse in figure i S1 = mousedrag_i(Sw) S1 = draw(S1) end if the mouse is in figure j Sw = dragout_i(Sw) Sw = dragin_j(Sw) i = j end end S1 = mouseup_i(Sw) S1 = draw(S1) discard Sw
Example
Here is an example where a red cross can be moved between Figure One and Figure Two. The location of the cross is stored in Sysquake variables x and y for its coordinates, and i for the figure (1 for Figure One, 2 for Figure Two).
variable i, x, y init (i, x, y) = init figure "Figure one" draw draw(1, i, x, y) mousedrag (x, y) = drag(1, i, _id, _x1, _y1) dragin i = dragin(1) dragout dragout(1) figure "Figure two" draw draw(2, i, x, y) mousedrag (x, y) = drag(2, i, _id, _x1, _y1) dragin i = dragin(2) dragout dragout(2) function {@ function (i, x, y) = init i = 1; x = 0; y = 0; subplots('Figure one\tFigure two'); function draw(fig, i, x, y) scale('equal', [-5, 5, -5, 5]); if i == fig plot(x, y, 'xR', 1); else text(0, 0, '(empty)'); end function (x, y) = drag(fig, i, _id, _x1, _y1) if isempty(_id); cancel; end x = _x1; y = _y1; function fig = dragin(fig) fprintf('dragin %d\n', fig); function dragout(fig) fprintf('dragout %d\n', fig); @}
Here is what happens when the cross is dragged from Figure One to Figure Two:
- Figure One's mousedrag handler is called with fig=1 as long as the mouse is not moved over Figure Two
- When the mouse enters Figure Two, since Figure One (the source figure) has a dragout handler and Figure Two (the target figure) has a dragin handler, Sysquake calls Figure One's dragout handler with fig=1, then Figure Two's dragin handler with fig=2; the dragin handler is declared in such a way that Sysquake variable i is set to the target figure number, i.e. 2. The cross is displayed in Figure Two.
- Figure Two's mousedrag handler is called with fig=2. Figure One's mousedrag handler is not called anymore.
A dragout operation is prevented by the dragout handler if it calls cancel, either without argument to abort completely the mousedrag operation or as cancel(false) to continue the mousedrag in the initial figure. Calling cancel in the dragin handler has an effect only on the drag in the second figure.
User Interface Options
By default, Sysquake lets the user of an SQ file change the layout of figures with the Layout menu, the Plots menu which is filled with all the figures defined in the SQ file, and the ability to drag figures with the mouse. The developer of the SQ file can disable these features by adding the following statement to the SQ file:
userinterface noplotchoice
The supported options of userinterface are enumerated in the table below:
Option | Effect |
---|---|
figoptions | menu items for figure options (default) |
nofigoptions | no menu items for figure options |
noplotchoice | fixed set of figures |
noselectall | no menu entry "Select All" |
plotchoice | options to change figures |
selectall | menu entry "Select All" (default) |
Languages
Some elements contain text. A single SQ file can contain multiple translations of these elements. When the SQ file is loaded, only elements corresponding to a single language are displayed; the language can be selected from a menu which enumerates all the translations it contains.
Elements declared for a specific language must be enclosed between beginlanguage and endlanguage:
beginlanguage "Language;code" // declarations endlanguage
The string following beginlanguage contains the language name (such as Français), followed optionally by a semicolon and the ISO 639 code of the language (such as fr). The language name is used in the user interface; the code of the language is used on some platforms to obtain the default language.
A single SQ file can contain multiple language specifications for the same language. When the first specification contains both the language name and the language code, successive declarations for the same language can omit the language name.
Any declaration can be placed under the scope of beginlanguage; then it becomes language-specific, contrary to declarations outside of any beginlanguage section which are valid for all the languages. Language-specific init handlers are used in a special way: contrary to non-language-specific init handlers, they are executed when the language is changed. This is especially useful to change the figures.
Instead of having different handlers for different languages, it is also possible to test in handlers which is the current language with function
Examples
In the following example, two languages are defined, English and French. Function definitions are omitted.
variable a, b init (a, b) = init beginlanguage "English;en" title "Amounts" menu "Value of a" a = setA(a) init initFigEn figure "Chart" draw drawChart(a, b) endlanguage beginlanguage "Français;fr" title "Grandeurs" menu "Valeur de a" a = setA(a) init initFigFr figure "Graphique" draw drawChart(a, b) endlanguage functions {@ function initFigEn subplots('Chart'); function initFigFr subplots('Graphique'); // ... @}
The following SQ file is equivalent, with multiple declarations for the same languages.
variable a, b init (a, b) = init beginlanguage "English;en" title "Amounts" endlanguage beginlanguage "Français;fr" title "Grandeurs" endlanguage beginlanguage "en" menu "Value of a" a = setA(a) endlanguage beginlanguage "fr" menu "Valeur de a" a = setA(a) endlanguage beginlanguage "en" figure "Chart" draw drawChart(a, b) endlanguage beginlanguage "fr" figure "Graphique" draw drawChart(a, b) endlanguage functions {@ // ... @}
Idle Handler
In addition to menu and mouse handlers, which modify Sysquake variables when the user performs some action, SQ files can define an idle handler, which is called periodically. Variables are modified without adding a new undo level. An idle handler is declared as follows:
idle (output_variables) = idleHandler(input_variables)
The rate at which the idle handler is executed depends on the operating system. It usually depends on the activity of the computer, such as the user interface or the network. You can give hints to Sysquake by adding a special output argument to the idle handler:
Name | Description |
---|---|
_idlerate | time rate, in seconds, for calling the idle handler |
_idleamount | proportion of time for idle processing (between 0 and 1) |
Only one of these arguments should be used. It should be stressed that the use of _idlerate does not guarantee real-time execution. Sysquake limits the time it gives to the idle handler to permit user interaction. It also enforces a maximum delay to make sure the idle handler is not blocked forever in case _idlerate is set to 0.
There may be only one idle handler per SQ file. It is useful when some external data can be acquired and displayed continuously, for long optimization procedures to display their progress, or for simple animations.
Example
variable x init x = init idle (x, _idlerate) = idle(x) functions {@ function x = init x = 0; function (x, _idlerate) = idle(x) // increment and display x x = x + 1 // should be called about every second _idlerate = 1; @}
Import and Export Handlers
The most obvious way to exchange data between different SQ files and with other applications is with Copy/Paste in dialog boxes or via files. This has four drawbacks:
- it involves several steps;
- the amount of data is limited;
- since no common interchange format has been defined, editing (manually or via computation in the command line) may be required;
- a significant development effort is required.
Sysquake solves this problem with a generalized import/export mechanism. There are two handler types to support this mechanism, export and import, with a syntax similar to menu handlers. They are collected respectively in submenus "Copy As" and "Paste As" in the Edit menu. Export handlers implement the conversion from variables to some well-defined LME data type, such as a matrix or a structure. Import handlers do the same in the opposite way. There is no limit to the number of import and export handlers. Handlers should be defined for complete sets of data which can easily be grasped by the user rather than variables which make sense only to the programmer: for instance, a set of points is better than their X-axis coordinates.
Import handlers are declared as
import "menu entry name" (outvar) = fn(invar,_xdatatype,_xdata)
or
import "menu entry name" _enabled(b) ... (outvar) = fn(invar,_xdatatype,_xdata)
The menu entry name is inserted in the Edit/Paste As submenu. The entry is enabled when the expression invoked with _enabled is true, or always if _enabled is missing. When the menu entry is selected, the handler is executed the usual way (i.e. a new undo frame is created, the handler is executed, and the changes are accepted unless an error occurs or the cancel function is executed by the handler). Both the _enabled expression and the handler arguments may include the special variable _xdatatype, which contains a string describing the type of the data in the clipboard (see below); the handler typically also uses as input _xdata, which contains the clipboard contents as an LME object.
Name | Description |
---|---|
_xdata | clipboard converted to an LME object |
_xdatatype | type of the contents of the clipboard |
The import handlers may be laid out like the figures and the menu entries, with separators. If an entry has an empty name, it is merged with the previous entry with a nonempty name: a single menu entry is displayed, it is enabled if any of the _enabled expressions is true, and the first handler for which the _enabled expression is true is executed. In the following example, points stored in arrays x and y are set by importing either an n-my-2 real array (type 'xy') or an n-by-1 complex array (type 'complex array').
import "Points" _enable(strcmp(_xdatatype,'xy')) ... (x,y)=importXY(_xdata) import "" _enable(strcmp(_xdatatype,'complex array')) ... (x,y)=importC(_xdata) functions {@ function (x,y)=importXY(xdata) x = xdata(:,1); y = xdata(:,2); function (x,y)=importC(xdata) x = real(xdata(:)); y = imag(xdata(:)); @}
Export handlers are declared as
export "menu entry name" (_xdata,_xdatatype) = fn(invar)
or
export "menu entry name" _enabled(b) ... (_xdata,_xdatatype) = fn(invar)
The menu entry name is inserted in the Edit/Copy As submenu. The entry is enabled when the expression invoked with _enabled is true, or always if _enabled is missing. When the menu entry is selected, the handler is executed, but no new stack frame is created. If the handler does not throw any error or cancel, the contents of _xdata is copied to the clipboard, as data of type _xdatatype if the argument exists or as native data (tab-separated array for a real matrix or text for a string) if _xdatatype is missing.
Format of the interchange data
There are two formats of data used for exchange with the export and import handlers: raw data and structured data. Raw data used when the export handler does not output an _xdatatype argument. They also contain text: strings are output literally, and the real part of matrices is output as tabbed arrays of numbers. In both cases, end-of-lines are platform-dependent (LF for OS X and Linux, and CRLF for Windows). Other data types (such as structures) are not supported.
Structured data represents a complex type exported with an explicit _xdatatype; it contains text, whose first line is
%SQ xdata "datatype"
where datatype corresponds directly to the value of the argument _xdatatype set by the export handler; the remaining line(s) is a textual representation (as generated with dumpvar) of _xdata.
Data types are strings which are used to ensure the compatibility between export and import handlers. Official types, defined by Calerga, do not begin with "x-"; user types should begin with "x-" to avoid type name clash in the future. Here is a list of the current official types.
- unknown
- any LME type
- string
- string
- real array
- matrix of real numbers
- complex array
- matrix of complex numbers
- polynomial
- polynomial whose real coefficients are given in descending powers as a row vector
- samples
- tf s
- transfer function in the Laplace domain given by a structure of two fields:
- tf z
- transfer function in the z domain given by a structure of three fields:
- ss c
- state-space linear time-invariant continuous-time model with nu inputs, ny outputs and n states, given by a structure of four fields:
- ss d
- state-space linear time-invariant discrete-time model with nu inputs, ny outputs and n states, given by a structure of five fields:
- rst c
- polynomial linear time-invariant continuous-time controller given by
the structure of two or three fields described below; control signal
u is given byRu=S(r-y) orRu=Tr-Sy , wherey is the system output,r is the set-point, andR ,S , andT are three polynomials - rst d
- polynomial linear time-invariant discrete-time controller given by
the structure of two or three fields described below; control signal
u is given byRu=S(r-y) orRu=Tr-Sy , wherey is the system output,r is the set-point, andR ,S , andT are three polynomials in the forward-shift operatorq - function
- inline or anonymous function
- xy
- n-by-2 array of n points [X,Y]
Field | Description |
---|---|
num | numerator, row vector of coefficients in descending powers of s |
den | numerator, row vector of coefficients in descending powers of s |
Field | Description |
---|---|
num | numerator, row vector of coefficients in descending powers of z |
den | numerator, row vector of coefficients in descending powers of z |
Ts | sampling period |
Field | Description |
---|---|
A | n-by-n real matrix |
B | n-by-nu real matrix |
C | ny-by-n real matrix |
D | ny-by-nu real matrix |
Field | Description |
---|---|
A | n-by-n real matrix |
B | n-by-nu real matrix |
C | ny-by-n real matrix |
D | ny-by-nu real matrix |
Ts | sampling period |
Field | Description |
---|---|
R | row vector of coefficients in descending powers of s |
S | row vector of coefficients in descending powers of s |
T | row vector of coefficients in descending powers of s (optional) |
Ts | sampling period |
Field | Description |
---|---|
R | row vector of coefficients in descending powers of z |
S | row vector of coefficients in descending powers of z |
T | row vector of coefficients in descending powers of z (optional) |
Public handler
Public handlers are used to interact with an SQ file from another context. In most cases, Sysquake executes handlers defined in an SQ file in the context of this SQ file. For example, Sysquake knows which SQ file instance to address when a menu handler is executed, and which Sysquake variables and figures are involved. But in some advanced applications, it can be useful to execute the handler of another instance. This is the case when you want to transmit information across two SQ file instances, or to update graphics from a separate thread created with threadnew. Unlike libraries, the purpose of public handlers is not code reuse, but code execution in the context of another SQ file instance to change its SQ variables and usually trigger the update of graphics.
Public handlers, like all other handlers, are implemented as a single assignment. In addition to SQ variables, the special variable _xdata is used as input to provide data from the caller, and as output to give back data to the caller.
Here is a typical public handler declaration, with SQ variables in_sq and out_sq:
publichandler "phname" (out_sq, _xdata) = phfun(in_sq, _xdata)
The caller of the public handler provides and gets only the data passed in _xdata by calling sqcall:
out_xdata = sqcall(instanceid, 'phname', in_xdata);
Watch handler
Watch handlers are functions called when an SQ variable has been changed, for instance to send an updated parameter to a device you want to control from an SQ file. They can be declared either for a list of variables or for all SQ variables:
watch {var1,var2,...} watchfun(...) watch _all watchfun(...)
The watch handler is called after another handler has changed one of the watched variables. During mouse drag, calls to watch handlers are delayed until the end of the drag, even if no mouseup handler is declared, to reduce the number of calls.
The arguments of the watch handler function do not have to match the watched variables.
The watched variables themselves do not trigger calls to make handlers; but watch handler input arguments do, like any other handler.
Extension declaration
Extensions required by the SQ file can be declared as follows:
extension "extensionname"
The extension name is the name of the extension file without its suffix, such as longint for long integer support. Multiple extensions must be declared separately.
Currently, Sysquake Application Builder is the only application which requires the declaration of the extensions which are used. Extension declarations are ignored by other applications.