en fr

Disponible uniquement en anglais

Sysquake Pro – Table of Contents

Sysquake – 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:

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:

OptionEffect
figoptionsmenu items for figure options (default)
nofigoptionsno menu items for figure options
noplotchoicefixed set of figures
noselectallno menu entry "Select All"
plotchoiceoptions to change figures
selectallmenu 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:

NameDescription
_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:

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.

NameDescription
_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:
FieldDescription
num numerator, row vector of coefficients in descending powers of s
den numerator, row vector of coefficients in descending powers of s
tf z
transfer function in the z domain given by a structure of three fields:
FieldDescription
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
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:
FieldDescription
A n-by-n real matrix
B n-by-nu real matrix
C ny-by-n real matrix
D ny-by-nu real matrix
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:
FieldDescription
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
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 by Ru=S(r-y) or Ru=Tr-Sy, where y is the system output, r is the set-point, and R, S, and T are three polynomials
FieldDescription
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
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 by Ru=S(r-y) or Ru=Tr-Sy, where y is the system output, r is the set-point, and R, S, and T are three polynomials in the forward-shift operator q
FieldDescription
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)
function
inline or anonymous function
xy
n-by-2 array of n points [X,Y]

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.