Skip to content

Latest commit

 

History

History
654 lines (508 loc) · 49.8 KB

block-library-dev.md

File metadata and controls

654 lines (508 loc) · 49.8 KB

Application customization

The graphical user interface and the block library can be customized without changing the code itself. The appearance of elements is defined in SVG elements, and their usage (lists of elements, behavior, code generated by VPL blocks) is defined in JSON. The location of SVG and JSON is typically in separate files when the application is served by an HTTP server, or in the main HTML file if the file is opened directly in the browser (in that context, loading separate files is forbidden by the browser for security reasons). "Files" stored in the HTML file are placed in script elements with two mandatory attributes: type, the script type, should be application/json for JSON or application/svg for SVG; id, the element id, plays the same role as the filename of real files.

The entry point of all the definitions is the file ui.json (or script element with id="ui.json"). Its content is an object {"key1":value1,"key2":value2,...}.

Block library

Blocks are defined in ui.json as an array property with key blocks. If the value is null ("blocks":null), the default built-in (non-SVG) block definitions are used; if the value is an empty array, the block library is empty.

The appearance of blocks is defined by SVG elements specified by URI strings with syntax filename#id, where filename is the SVG file name or the SVG script element id, and id is the svg element id in that file.

Here are fragments of index-svg.html which illustrate the definition of the block button. Property main contains the URI of the svg element which is drawn for the button block. The filename part, blocks.svg, refers to the script element which contains the svg the element belongs to; and the id part, Ev_Buttons, is the element id in that svg.

<script type="application/json" id="ui.json">
...
"blocks": [
  ...
  {
  	"name": "button",
    "draw": [
      {
        "uri": "blocks.svg#event-button"
      }
    ],
  ...
]
...
</script>

<script type="image/svg+xml" id="blocks.svg">
...
<g id="event-button">
...
</g>
...
</script>

In json, block contain the following properties:

  • "name" (string, required): the block name, which should match VPL1 if possible.

  • "type" (string, required): one of "event", "state", "action", or "comment", which defines where the block is displayed (left for "event" or "state", right for "action" or "comment") and how it is used.

  • "modes" (array of strings, possibly empty, required): in which VPL mode the block is displayed. Contains "basic" if displayed in basic mode, "advanced" if displayed in advanced mode. This defines only the default block usage; customization can override it.

  • "draw" (array of objects, at least one element, required): list of the parts defining the block appearance including buttons, sliders, etc. Each part is described by an object with the following properties (only "uri" and "js" are implemented now):

    • "uri" (string, required unless "js" exists): uri of the svg element ("filename#id", with same filename for all elements in the same block)
    • "js" (string, required unless "uri" exists): JavaScript code which can draw to a canvas. The canvas context is stored in variable ctx, and the block parameters in variable $. The block area is between 0 and 1000 along both axes; path coordinates as well as line width, font size etc. must be scaled accordingly. This area is not clipped. Code is bracketed between ctx.save() and ctx.restore().
    • "scale" (number, optional, default: 1): scale at which the element is displayed
    • "dx" (number, optional, default: 0): horizontal displacement
    • "dy" (number, optional, default: 0): vertical displacement
  • "defaultParameters" (array of number, boolean or string values, optional): default values of the block parameters which define the state, in this order, of buttons (one value per button), radiobuttons (a single values for all radiobuttons), sliders (one value per slider), rotating controls (one value per control).

  • "typicalParameters" (same type and length as "defaultParameters", optional): values of the block parameters used to display the block in the block library.

  • "typicalParamSet" (array of elements the same type and length as "defaultParameters", optional): multiple values similar to "typicalParameters", to be used when the block has a very different appearance for different values of the parameters (e.g. in block "accelerometer" where the first parameter is 0 for tap, 1 for roll angle, or 2 for pitch angle). These values are used when exporting libraries as HTML.

  • "alwaysZoom" (boolean, optional): true to zoom block when clicked, irrespectively of minInteractiveBlockSize and minTouchInteractiveBlockSize. Default is false.

  • "buttons" (array of objects, optional): multi-state button definitions. Each button is described by an object with the following properties:

    • "id" (string, required): id of the svg element corresponding to the button. It should be contained in the element identified by "main".
    • "val" (array of numbers, booleans or strings, required): possible values for the button state. Each click toggles to the next value.
    • "st" (array of strings): style strings applied to svg elements when the corresponding value in val is active. Each style is defined by a fill and/or a stroke color, with the syntax "fill:color;stroke:color", or fill/stroke swapped, or one of them skipped without semicolon.
  • "radiobuttons" (array of objects, optional): radio button definitions (exclusive buttons). Each button is described by an object with the following properties:

    • "id" (string, required): id of the svg element corresponding to the button. It should be contained in the element identified by "main".
    • "val" (number, boolean or string, required): value for the set of radio buttons.
    • "st" (array of 2 strings): style strings applied to svg elements when the radio button is unselected or selected, respectively. Each style is defined by a fill and/or a stroke color, with the syntax "fill:color;stroke:color", or fill/stroke swapped, or one of them skipped without semicolon.
  • "pushbuttons" (array of objects, optional): definitions of buttons not associated to a specific parameter. The effect of clicking a pushbutton is to change globally the parameters, with more freedom (and complexity) than buttons or radiobuttons. They can be used to increment or decrement parameters. Parameters used only by pushbuttons can be reserved with "otherParameters". In pushbuttons objects, the following properties must be defined:

    • "id" (string, required): id of the svg element corresponding to the button. It should be contained in the element identified by "main".
    • "newParameters" (string, required): new value of the parameters when the button is clicked. The length of the parameter array must not be changed.
  • "sliders" (array of objects, optional): slider definitions. Each slider is described by an object with the following properties:

    • "id" (string, required): id of the svg element corresponding to the slider, including the thumb. If the element's height is larger than the element's width, the slider is vertical, else it's horizontal. The element bounds are used to limit the position of the middle of the thumb. In the svg, the thumb should be place at a position such that it does not overflow the slider bounding box (the middle position should be safe).
    • "thumbId" (string, required): id of the svg element corresponding to the thumb in the slider (the part which can be moved).
    • "lowerPartId" (string, optional): id of the svg element clipped at the thumb position so that only the part on the left of, or below, the thumb is displayed. Can be used to replicate the slider element with a different color to better show the value.
    • "min" (number, required): minimum value, stored in the block parameters.
    • "max" (number, required): maximum value, stored in the block parameters.
    • "snap" (array of numbers and/or strings, default: []): snap values to which the slider is attracted when the slider is within a relative distance of 10%. Numbers are fixed values; strings must contain a backtick-expression and are evaluated. They can refer to other parameters, typically other slider values (see "backtick-expressions" below).
    • "discrete" (non-empty array of numbers, default: null (continuous values possible)): like snap, but no other values are possible.
  • "rotating" (array of objects, optional): rotating control definitions. Each control is described by an object with the following properties:

    • "id" (string, required): id of the svg element corresponding to the rotating element, including the thumb.
    • "centerId" (string, required): id of the svg element whose center is the center of rotation.
    • "thumbId" (string, required): id of the svg element corresponding to the control part which can be moved.
    • "numSteps" (integer number): number of steps, positive for counting counter-clockwise, negative for counting clockwise. 0 means no rotation; if numSteps is even, minimum value is -numSteps/2 (for a 180-degree rotation) and maximum value is numSteps/2; if numSteps is odd, minimum value is -(numSteps-1)/2 and maximum value is (numSteps-1)/2. If "numSteps" property is not defined, value is in radians, counterclockwise, between -pi and pi.
  • "diffwheelmotion" (object, optional): robot with differential wheel motion. The robot, seen from above, is defined by a svg element, with wheel axis on the x axis and positive motion up. Wheel motion is specified with two sliders which should be defined with "sliders". Contains the following properties:

    • "id" (string, required): id of the svg element corresponding to the robot.
    • "dx" (number, optional): relative horizontal adjustment of the right wheel position (left wheel is moved symmetrically).
    • "dy" (number, optional): relative vertical adjustment of the wheels.
    • "adjscale" (number, optional): scale adjustment for the traces; 1 (default) means that the wheels are at the svg element boundaries, <1 that they are inside the svg element boundaries.
    • "color" (string, optional): trace color as a css color string (default: "black")
    • "linewidth" (number, optional): relative trace width. 1 (default) is the default line width of the block.
  • "score" (object, optional): notes for a monophonic melody. Notes are drawn as hollow circles for half notes, solid circles for quarter notes, and not drawn for pauses. They're centered on a grid. The "score" object contains the following properties:

    • "id" (string, required): id of the svg element where notes are drawn
    • "numHeights" (number, required): number of heights
    • "noteSize" (number, optional): relative note size adjustment factor. The normal size (default "noteSize" of 1) is height/numHeights
    • "linewidth" (number, optional): relative line width for half notes. 1 (default) is the default line width of the block.
  • "otherParameters" (number, optional, default 0): number of additional parameters, typically used by pushbuttons.

  • "styles" (array of objects, optional): style applied to SVG element. Each element contains the following properties:

    • "id" (string, required): id of the svg element style is applied, or not applied, to
    • "complement" (boolean, optional, default false): true to apply to all elements except with id
    • "st" (string, required): style string; usually contains backtick-expressions
  • "aseba" (object, optional): code fragments to generate Aseba language source code. Code fragments contain Aseba source code. Except for "clause" and "clauseAnd" which contain expression fragments, they can contain muliple lines, comments, empty lines, terminated by linefeeds (\n). Backticks mark JavaScript expressions which are evaluated to substitute block parameters; see below. The object contains the following properties (strings can be replaced with array of strings which are concatenated, to make the json file easier to read):

    • "initVarDecl" (array of strings, optional): code fragments for (global) variable declarations. Identical fragments (after backtick-expressions evaluation) are output only once.
    • "initCodeDecl" (array of strings, optional): code fragments for subroutine declarations. Identical fragments (after backtick-expressions evaluation) are output only once.
    • "initCodeExec" (array of strings, optional): code fragments for initialization. Identical fragments (after backtick-expressions evaluation) are output only once.
    • "sectionBegin" (string, optional, event block): beginning of a section (typically an onevent block). Identical sections are collected and a single sectionBegin and sectionEnd are output.
    • "sectionEnd" (string, optional, event block): end of a section (typically unused for Aseba code).
    • "sectionPreamble" (string, optional, event block): code at beginning of sectionBegin/sectionEnd (enforce section even when the block is used only as state)
    • "clauseInit" (string, optional, event block): code fragments for clause initialization. Identical fragments in the same section (after backtick-expressions evaluation) are output only once after "sectionBegin". Used to initialize temporary values used in clauses.
    • "clause" (string, optional, event block): clause expression (condition) used in "when" Aseba statement for the whole block.
    • "clauseAnd" (string, optional, event block): clause subsexpression. "clause" and "clauseAnd" cannot be used in the same block. "clauseAnd" expressions are produced for each parameter; the whole clause is obtained by joining "clauseAnd" expressions with the "and" operator.
    • "clauseAlwaysEval" (boolean, optional, default not): if true, clause or clauseAnd are in an if statement instead of when.
    • "clauseAsCondition" (string, optional, event block): used in lieu of "clause" when the block is added as a condition next to an event.
    • "statement" (string, required, action block): code fragment for action.
    • "statement1" (string, optional, action or event block): code subfragment for event cache or action. "statement" and "statement1" cannot be used in the same block. "statement1" statements are produced for each parameter; the whole statement is obtained by concatenating "statement1" statements.
  • "l2" (object, optional): code fragments to generate L2 language source code. Same properties as "aseba".

Action block are implemented with "statement" or "statement1". If global variables are used, they are declared in "initVarDecl". Any initialization must be defined in "initCodeExec". Only one copy of each "initVarDecl" and "initCodeExec" code fragments is output. While they can contain multiple variables or commands, it is recommended to split them into smaller fragments to avoid writing to the final program unused code.

Event and state blocks are more involved. "initVarDecl" and "initCodeExec" have the same role as for action blocks. Basically, event blocks are conditions, but they are evaluated in two distinct contexts: as a single, instantaneous, unique occurrence (the "event" side); and as a state (the "state" side). Consider a single proximity sensor, and the clause defined as true when the sensor value is higher than a threshold. The event side occurs once every time the sensor detects a transition from a value lower than the threshold to a value higher. The state side is true when the current sensor value is higher. The event side is used for the first event block, the state side is used for all the other event blocks.

On the Thymio, few firmware-level events (what triggers "onevent" in Aseba) correspond to our definition of the event side. The remote control and the timers do, capacitive buttons and proximity sensors do not. It is up to the program generated from VPL to abstract from the firmware and run as expected. Continuing from the single proximity sensor example and adding key event, consider the following VPL program:

[prox > threshold] [key center] -> [action1]
[prox > threshold]              -> [action2]

Aseba code could be as follows (actually an array eventCache is allocated instead of variables proxClose and keyCenter):

var proxClose
var keyCenter
proxClose = 0
keyCenter = 0

onevent prox
  when prox.value > 500 do
    proxClose = 1
  end

onevent key
  when key.center != 0 do
    keyCenter = 1
  end

onevent timer1
  if (proxClose != 0) and (key.center != 0) then
    # action1
    proxClose = 0
  end
  if keyCenter != 0 then
    # action2
    keyCenter = 0
  end

To support these blocks, the code definition is as follows:

{
  "name": "prox",
  "aseba": {
    "initVarDecl": [
      "var proxClose\n"
    ],
    "initCodeDecl": [
      "proxClose = 0\n"
    ],
    "sectionBegin": "onevent prox\n",
    "clause": "prox.value > 500"
  }
},
{
  "name": "key center",
  "aseba": {
    "initVarDecl": [
      "var proxClose\n"
    ],
    "initCodeDecl": [
      "proxClose = 0\n"
    ],
    "sectionBegin": "onevent key\n",
    "clause": "key.center != 0"
  }
}

When an event block has parameters, possibly with a vector of values, a single boolean variable must capture the whole transition from false to true, and be unique for each different set of parameters event when it is repeated in different instances of the same block. Parameters should be different enough so that the differences are obvious in the block appearance. An array variable eventCache is declared automatically with the appropriate size.

A proximity sensor with a vector of 5 values could be defined as follows.

{
  "name": "prox 5",
  "aseba": {
    "sectionBegin": "onevent prox\n",
    "clauseAnd": "prox[`i`].value > 500"
  }
}

The VPL program

[prox[2] > 500 and prox[3] > 500] -> [action]

would be compiled as

var eventCache = [0]

onevent prox
  when (prox[2].value > 500) and (prox[3] > 500) do
    eventCache[0] = 1
  end

onevent timer1
  if eventCache[0] then
    # action
    eventCache[0] = 0
  end

Special blocks

Special blocks contain definitions for specific purposes. They cannot be manipulated by the user to build rules. Their "type" property should be "hidden", and their name start with an !.

"!empty event": contains the svg elements displayed as a hint on the left part of the rule to accept another event block.

"!empty action": contains the svg elements displayed as a hint on the right part of the rule to accept another action block.

"!init": contains initialization code, in initVarDecl for variable declarations if any, initCodeDecl for function declarations if any, and initCodeExec for intialization code if any.

"!stop": contains the code to stop the robot, executed when the Stop button is clicked.

"!volume": contains the code to set the robot volume, from 0 (muted) to 10 (max). The volume is specified in the single parameter.

Example:

{
  ...
  "blocks": [
  	{
  	  "name": "!empty event",
  	  "type": "hidden",
  	  "draw": [ { "uri": "blocks.svg#event-empty" } ]
  	},
  	{
  	  "name": "!empty action",
  	  "type": "hidden",
  	  "draw": [ { "uri": "blocks.svg#action-empty" } ]
  	},
  	{
  	  "name": "!stop",
  	  "type": "hidden",
  	  "aseba": { "statement": "motor.left.target = 0\nmotor.right.target = 0\n" }
  	},
  	...
  ],
  ...
}

Block order

By default, all blocks defined in array "blocks" are available in that order, with event and state blocks on the left and action and remark blocks on the right, possibly filtered by the customization. Blocks can be reorder with a simple array of names in the property "blockList" of ui.json. If this property is defined, missing blocks are totally ignored; they cannot even be used in programs loaded from files. Blocks with type "hidden" are always available internally and must not be listed in blockList array.

Backtick-expressions

Code fragments, styles, and some other properties can contain backtick-expressions, i.e. JavaScript expressions enclosed between backticks in normal double-quoted JSON strings. The expression is evaluated and its result replaces the whole backtick-expression in the string. A string can contain multiple backtick-expressions. The following variables are defined:

  • $: array of block parameters
  • i: index of the parameter (used in clauseAnd and statement1 code fragments and in slider's "snap" property)
  • rgb: function which converts an array of RGB values between 0 and 1 to an RGB value suited for representing an RGB led (saturated colors are mapped to themselves, but [0,0,0] (led switched off) is mapped to gray).

Miscellaneous settings

Property "miscSettings" contains VPL global settings which aren't related to the user interface:

  • "advancedModeEnabled" (boolean, default true): true to enable advanced mode, false to have a single mode (basic); can be overridden by query option advmode (see below)
  • "basicMultiEvent" (boolean, default false): true to allow multiple event blocks in basic mode
  • "advancedMultiEvent" (boolean, default false): true to allow multiple event blocks in advanced mode
  • "viewRelativeSizes" (object, default {"vpl":1,"src":1,"sim":1}): relative size of vpl, src and sim views

Hardcoded blocks

Even when blocks are mostly hardcoded in JavaScript, properties related to code generation can be specified in JSON overlays. In that case, the following property should be defined:

  • "hardcoded-gui": (boolean, default false): true to use built-in block definitions and overlay code generation properties defined in JSON.

Toolbars

Toolbars can also be defined with SVG elements. Buttons are identified with a string id, such as "vpl:new" for the button which resets the VPL program in the VPL view. Redefining toolbars is the result of two independent things:

  • toolbar elements, as an array of button identifies + spacing for each toolbar (currently "vpl", "vpl2", "editor" and "simulator");
  • button appearance, defined as sets of SVG elements for the different button states (normal, pressed, selected, disabled, or any combination).

Toolbars and buttons can be defined either directly in the main ui.json file (top-level property "toolbars" and "buttons", respectively), or in overlay json files referenced in the top-level property "overlays" of ui.json. SVG files must always be enumerated in ui.json, in the top-level property "svgFilenames".

Toolbar definitions

Property "toolbars" is an object with one property per toolbar, with name "vpl" (main toolbar at top of vpl view), "vpl2" (optional toolbar at bottom of vpl view between the event and action blocs), "editor" (source code editor view) or "simulator" (simulator view). Property values are arrays of strings. Each string corresponds either to a button id or to one of the following special values:

  • "!space", a fixed space slightly larger than the usual space, used to indicate subgroups in groups of related actions;
  • "!stretch", a larger space calculated so that the whole toolbar fills the available horizontal space. All "!stretch" spaces have the same length. They're used to separate groups of unrelated items;
  • "!!space", like "!space" but never discarded (see below)
  • "!!stretch", like "!stretch" but never discarded (see below)

When toolbars are customized by hiding some buttons, multiple "!space" and "!stretch" items may appear in sequences. They're collapsed into a single "!stretch", or a single "!space" for sequences of multiple "!space" items only. Leading and trailing sequences of "!space" and "!stretch" are entirely removed. When spaces should be preserved (e.g. a leading stretch to flush buttons to the right), "!!space" and "!!stretch" items should be used instead.

Buttons for actions which are permanently disabled, such as "vpl:run" when neither the robot nor the simulator is available, or "vpl:teacher" when the user has a student role, are not displayed.

Here is the list of button ids for the VPL view (toolbars "vpl" or "vpl2"):

  • "vpl:close": close the VPL view
  • "vpl:about": display an about box (modal box with HTML defined in property "about.html" of property "fragments" of ui.json)
  • "vpl:help": display a help box (modal box with HTML defined in property "help.html" of property "fragments" of ui.json)
  • "vpl:statement": display a statement box (modal box with HTML which can be sent by teacher from a connected dashboard)
  • "vpl:readonly": read-only indicator when the program cannot be modified (new, load, advanced, undo, redo, duplicate, disabled, lock, trashcan, teacher commands are disabled)
  • "vpl:new": reset VPL program to start a new program
  • "vpl:save": download the VPL program
  • "vpl:exportToHTML": export the VPL program to a self-contained HTML file
  • "vpl:upload": upload VPL program to the central repository or to the teacher computer (state is "empty" if the program is empty, "uploaded" if the program on the screen is the uploaded program, "canUpload" if the program has never been uploaded, or "canUploadAgain" if the program has already been uploaded but is not the one on the screen)
  • "vpl:text": switch to the text programming language editor (Aseba, L2 or JavaScript)
  • "vpl:text-toggle": toggle visibility of text editor (replaces "vpl:text" and "src:close")
  • "vpl:advanced": toggle between basic and advanced VPL mode
  • "vpl:add-comment": add a comment to the VPL program
  • "vpl:undo": undo last change
  • "vpl:redo": redo last undone change
  • "vpl:run": run the VPL program with the Thymio or the simulator (state is "empty", "running", "error", "canLoad", or "canReload" depending on the VPL program and whether it's been run and modified)
  • "vpl:stop": stop the VPL program and blink the leds
  • "vpl:connected": connection indicator (no action, always disabled; selected if connected to a robot, unselected if no connection with a robot; state is "monitored" if connected with a supervisor application (teacher dashboard), "nonmonitored" if disconnected, or "" (empty string) if no supervisor)
  • "vpl:robot": toggle between all the robots specified in option "robot" in the query string (see below; hidden unless there are at least two robots; state is the robot name, such as "thymio" or "sim")
  • "vpl:sim": switch to the simulator view
  • "vpl:duplicate": duplicate a rule (drag target)
  • "vpl:disable": toggle a rule or block between disabled and enabled states (drag target)
  • "vpl:lock": toggle a rule or block between disabled and enabled states (drag target, not implemented)
  • "vpl:trashcan": delete a rule or block (drag target)
  • "vpl:teacher": toggle between the normal and the customization states
  • "vpl:teacher-reset": reset the available toolbar buttons and VPL blocks to the standard sets
  • "vpl:teacher-save": download customized state (like "vpl:save", but without the VPL program)
  • "vpl:teacher-setasnew": toggle between setting current program and customized state as initial program after "vpl:new", or default empty program with customized state (automatic if "vpl:teacher-setasnew" isn't used in top or bottom vpl toolbar)

The following ids are for passive text strings:

  • "vpl:message-error": vpl error message
  • "vpl:message-warning": vpl warning message
  • "vpl:message-empty": no error or warning message (placeholder for alignment)
  • "vpl:filename": vpl filename and username, whichever are defined

Here is the list of button ids for the Editor view:

  • "src:close": close the editor view
  • "src:new": clear the text program
  • "src:save": download the text program
  • "src:vpl": switch to the VPL view
  • "src:locked": toggle between the locked state where the text program corresponds to the VPL program and cannot be edited, and the unlocked state where the text program can be modified
  • "src:language": switch to the next programming language (Aseba, L2, JavaScript or Python); state is "aseba", "l2", "asm", "js", or "python"
  • "src:disass": toggle between the text programming language and the bytecode disassembly (for Aseba and L2)
  • "src:run": run the text program with the Thymio or the simulator (state is "empty" or "canLoad" depending on the source code)
  • "src:stop": stop the text program and blink the leds
  • "src:connected": connection indicator (no action; enabled if connected, disabled if no connection)
  • "src:sim": switch to the simulator view
  • "src:teacher": toggle between the normal and the customization states
  • "src:teacher-reset": reset the available toolbar buttons and VPL blocks to the standard sets

Here is the list of button ids for the Simulator view:

  • "sim:close": close the simulator view
  • "sim:restart": restart the program with the robot in the middle of the playground
  • "sim:pause": toggle the simulation between the execution state and the suspended state
  • "sim:speedup": change the speedup factor between x1 (real-time), x2, x5, x10 (accelerated), :2 (slowed down); state is the acceleration factor (0.5, 1, 2, 5, or 10)
  • "sim:noise": toggle simulated noise for sensor measurements
  • "sim:pen": toggle pen between up and down
  • "sim:clear": clear the pen trace (revert to the ground map)
  • "sim:map-kind": change the map being displayed between ground (for ground sensor, combined with pen traces), obstacles (for proximity sensors) and height (for acceleration sensors); state is "ground", "obstacles" or "height"
  • "sim:map": toggle the map being displayed between on and off
  • "sim:vpl": switch to the VPL view
  • "sim:text": switch to text programming language editor
  • "sim:teacher": toggle between the normal and the customization states
  • "sim:teacher-reset": reset the available toolbar buttons and VPL blocks to the standard sets
  • "sim-event:forward": send a button.forward event to the simulated robot
  • "sim-event:backward": send a button.backward event to the simulated robot
  • "sim-event:left": send a button.left event to the simulated robot
  • "sim-event:right": send a button.right event to the simulated robot
  • "sim-event:center": send a button.center event to the simulated robot
  • "sim-event:clap": send a mic event to the simulated robot
  • "sim-event:tap": send a tap event to the simulated robot

SVG buttons

Property "buttons" is an array with one element per button appearance. Each button appearance is an object with the following properties:

  • "name": button name (see "Toolbar definitions" above)
  • "state": array of strings which restricts when the appearance is used: "pressed" (the button is being clicked or tapped, or the target of a drop), "unpressed" (the button is not being clicked or tapped, nor the target of a drop), "selected" (the button corresponds to a state which is ON), "unselected" (the button corresponds to a state which is OFF), "disabled" (the action is disabled), "enabled" (the action is enabled). In addition, strings starting with "=" specify which state to select for multi-state buttons such as "src:language" or "sim:map"; for example "=aseba" for the "src:language" button would be used when the Aseba language is selected. The first appearance match is used; typically appearance with "state" set to ["disabled"], ["pressed"], ["selected"] (for toggle buttons only), and [] (normal appearance) are defined in that order.
  • "draw": array of objects defining the appearance of buttons, like for blocks (see above). They have a "uri" property for svg or a "js" property for JavaScript code, and optionally an "alpha" property (number, 1=opaque, 0=transparent) and a "debug" property (string, displayed centered over the widget). Elements in "draw" are rendered starting with the first one, with the last one in the foreground. In JavaScript code ("js" property), the canvas context is stored in variable ctx, and the button state in variable $, an object with properties $.enabled, $.disabled, $.selected, $.unselected, $.pressed, $.unpressed, and $.state. The button area is between 0 and 1000 along both axes; path coordinates as well as line width, font size etc. must be scaled accordingly. This area is not clipped. Code is bracketed between ctx.save() and ctx.restore().

Elements of "buttons" with id "vpl:message-error", "vpl:message-warning" and "vpl:filename" (not real buttons, but placeholders to display error or warning messages, or filename/username, in a toolbar) should not be redefined in SVG. The text style can be changed in css.

If the value of property "buttons" is null ("buttons":null), the default built-in (non-SVG) button definitions are used. Otherwise, undefined buttons are displayed as squares with the button id and properties displayed; this can be useful during development.

SVG widgets

Property "widgets" is an array with one element per widget. A widget is a static graphical element used in the graphical user interface. They're identified by one of the following names:

  • "vpl:then": placed between events and actions (colon in VPL1)
  • "vpl:error": error marker displayed close to rules with errors (question mark in a circle in VPL1)
  • "vpl:warning": warning marker displayed closed to rules with warnings (minor issues which still permit to run the program)
  • "vpl:moreHigh": hint displayed at the top of block lib (events or actions) when overflow is scroll (see section "Stylesheet" below) and the blocks could be scrolled down to show more
  • "vpl:moreLow": hint displayed at the bottom of block lib (events or actions) when overflow is scroll and the blocks could be scrolled down to show more
  • "vpl:customize": displayed in lieu of vpl program during ui customization when "vpl:teacher" is selected

Widgets are scaled to fill their css box (see below). The box id for widget "vpl:then" is "widget-then", and so on.

Each widget appearance is an object with the following properties:

  • "name": widget name (see above)
  • "svg": array of objects containing a "uri" or "js" property, like for blocks (see above), and optionally an "alpha" property (number, 1=opaque, 0=transparent), and a "debug" property (string, displayed centered over the widget). SVG elements are rendered starting with the first one, with the last one in the foreground.

If the value of property "widgets" is null ("widgets":null), the default built-in (non-SVG) widget definitions are used. Otherwise, undefined widgets are empty (nothing is displayed).

SVG implementation

Here is an overview of the SVG subset which is supported. Unsupported features are ignored.

  • elements: circle, g, line, path, polygon, rect, svg, text
  • style properties: fill, font-family, font-size, opacity, stroke, stroke-dasharray, stroke-dashoffset, stroke-linecap, stroke-linejoin, stroke-miterlimit, stroke-width, visibility
  • gradients: linearGradient, radialGradient

Stylesheet

The general layout of the user interface is subject to one or multiple stylesheets. The syntax is based on CSS. Stylesheets must be enumerated in the property "css" in the main ui.json file or script element; the value is an array of filenames (or script id) as strings.

Currently, some style-related parameters are still fixed in JSON (see "Global style settings" below), but eventually all properties should be defined in CSS. Unknown element names, classes, pseudo-classes and properties are ignored.

Style properties follow CSS box model (see https://www.w3.org/TR/css-box-3/). Default padding, border and margin are 0. Default size is what's required for the content (such as a block or a widget bounding box), or the available width or height, or 0 for empty boxes (separators).

Box properties:

  • padding-left, padding-right, padding-top, padding-bottom
  • padding
  • border-left-width, border-right-width, border-top-width, border-bottom-width
  • border-left-style, border-right-style, border-top-style, border-bottom-style
  • border-left-color, border-right-color, border-top-color, border-bottom-color
  • border-left, border-right, border-top, border-bottom
  • border
  • border-width
  • border-color
  • border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius
  • border-radius
  • border-top-left-cut, border-top-right-cut, border-bottom-right-cut, border-bottom-left-cut (same as *-radius, but straight cut instead of rounded)
  • border-cut (same as *-radius, but straight cut instead of rounded)
  • border-corner-length (length of border visible from each corner)
  • margin-left, margin-right, margin-top, margin-bottom
  • margin
  • backdrop-color (square box, typically to complement rounded or cut corners)
  • background-color
  • background (for background-color property only)
  • box-shadow (inset and spread radius ignored, one shadow only)
  • width, height
  • min-width, min-height (priority over max-width and max-height if inconsistent)
  • max-width, max-height
  • color
  • font
  • overflow (used in block-library only)
  • vertical-align (used to align blocks in rules)

Line properties:

  • color
  • line-width
  • line-style
  • line-cap

Values:

  • lengths: floating-point value with unit (px, cm, mm, in, pc, pt, vw, vh, vmin, vmax, ww, wh, wmin, wmax, %), or 0
  • angles: floating-point value with unit (rad, deg, grad, turn)
  • colors: #xxxxxx or #xxx or one of the colors defined in https://www.w3.org/TR/css-color-3/#svg-color
  • line styles: none, hidden, dotted, dashed, solid, or double
  • line caps: butt, round, square
  • font: see https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#font-prop
  • border-left, border-right, border-top, border-bottom, line: 1, 2 or 3 properties for line width (length), color and line style in any order
  • overflow: wrap (default) or scroll
  • vertical-align: top, middle (default), or bottom

Functions min and max are supported in lengths.

Box elements:

  • view (classes: vpl, sim, src)
  • widget (id: widget-error, widget-warning, widget-then, widget-moreLow, widget-moreHigh; pseudo-class: small)
  • button (classes: vpl, sim, src, top, bottom; pseudo-class for #vpl-filename: edited)
  • separator (classes: vpl, sim, src, top, bottom)
  • toolbar (classes: vpl, sim, src, top, bottom)
  • vpl
  • block (classes: event, event-main, event-aux, action, state, comment (class of block), empty, library (as displayed in block-library elements); pseudo-class: small (when they must be zoomed for interaction), only-child (for class empty only))
  • block-container (classes: error, warning; used only in rules, not in block-library)
  • rule (class: comment; pseudo-classes: small, edited)
  • block-library (classes: event (for event and state blocks), action (for action and comment blocks))
  • button-small (small buttons in simulator)
  • sim-controller (area where robot control buttons and indicators are displayed)
  • sim-playground-area (box which fills the area where the playground is displayed)
  • sim-playground (box which fits tightly the area where maps are displayed and the robot can be located)
  • overlay-rectangle (box displayed over other element; classes: disabled, button, vpl, rule, block, drop-target, kbd-selected, kbd-target)
  • hint (box at bottom left where block and toolbar button hints are displayed)

Line elements:

  • conflict-line (classes: error, warning)
  • crossout-line (classes: button, vpl, rule, block, library; additional properties line-angle and line-overflow)

Text translation

Text messages can be translated to languages other than English. Translations are defined in dictionaries where the key is the English message and the value is the translated value. Translation dictionaries are specified under the key "i18n" at the top level. Here is a partial example:

{
  ...
  "i18n": {
    "fr": {
      "Missing action block": "Il manque un bloc d'action",
      ...
    },
    "it": {
      ...
    }
  },
  ...
}

Languages and messages can be split into multiple overlays.

Global style settings

Some global style settings can be specified in a top-level object named "style". Here is the list of properties it can contain, their type and their default values.

  • "scrollbarThumbColor" (string, default: "navy"): color of scrollbar thumbs

  • "scrollbarBackgroundColor" (string, default: "#ccc"): color of scrollbar background (rectangular shape behind the thumb)

  • "scrollbarWidth" (number, default: 5): scrollbar width in css pixels

  • "blockLineWidth" (number, default: based on block size): line width used in blocks

  • "minTemplateSize" (number, default: 32): minimum block size in libraries

  • "minInteractiveBlockSize" (number, default: 60): minimum block size where direct manipulation of interactive controls (buttons, sliders etc.) is possible; if smaller, a zoomed version is displayed when the block is clicked or touched

  • "minTouchInteractiveBlockSize" (number, default: 120): same as "minInteractiveBlockSize", but for touch events, typically on smartphones and tablets

  • "eventRightAlign" (boolean, default: false): true to align event blocks on the right

  • "ruleMarks" (string, default: "#bbb"): color of rule marks (colon dots)

Auxiliary HTML and CSS documents

Some HTML and CSS documents are defined as string properties of the top-level object named "fragments". For additional flexibility, html can contain a simple iframe element which loads a separate HTML document. Here is a definition for the About box:

"<iframe src=\"vpl-about.html\" style=\"width:100%;height:100%;border:none;\"></iframe>"

The following properties are used:

  • "about.html": html document displayed in the About box.
  • "help.html": html document displayed in the Help box.
  • "vpl-export-html.css": css written into html files generated by button "vpl:exportToHTML".

In documents "about.html" and "help.html", UIROOT is replaced with the location of ui.json, or by global variable window["vplUIRoot"] if defined.

Options passed in query string

The entry point of the web application is defined in vpl-main.js, in an event listener function for "load". Options can be specified in query parameters, i.e. in key=value pairs, separated by ampersand following a question mark. In addition, if the variable window["vplQueryOptions"] is defined (typically in a script element in the html file which contains VPL3), its string value is used for options not specified in the url's query string.

The following options are supported:

  • appearance: classic (icons and blocks defined in JavaScript) or svg (default) (icons and blocks defined in SVG and json).
  • multiview: true (default) to enable the display of multiple views simultaneously (main vpl view, text source code and simulator), false to force a single view filling all the available space.
  • advmode: false (default) to disable advanced VPL mode, true to enable it
  • language: programming language the vpl program is converted to. aseba (default), l2 (C-like syntax with functions, local variables, boolean and fixed-point values, and multi-dim arrays), asm (assembly language for Aseba bytecode), python, or js. Not all the languages are compatible with the Thymio or the simulator.
  • cssdebug: true to display the padding and margin rectangles of css boxes, or false (default).
  • adv: true to enable advanced features such as the Aseba virtual machine disassembler, or false (default).
  • blur: radius of blur filter applied to canvas in 0.1px units (default 0), to simulate vision deficiency.
  • grayscale: percentage of grayscale filter applied to canvas (default 0), to simulate grayscale printing, low-quality displays such as beamers where color shifts are common, or vision deficiency.
  • view: list of initial views (default vpl). Views (vpl, src or sim) are separated by +.
  • robot: device(s) code is sent to for execution. thymio for a Thymio via asebahttp (supported language: aseba), thymio-tdm for a Thymio via the Thymio Device Manager (supported language: aseba), sim for the simulator (supported languages: aseba, l2, and js), or undefined for no execution. Multiple devices can be specified, separated with +; e.g. robot=thymio-tdm+sim. In that case, button "vpl:robot" toggles between devices. Connection parameters can be passed as hash parameters (same as query parameters but after the hash character '#' instead of question mark '?'). For thymio, asebahttp=... specifies the url of asebahttp or Thymio Web Bridge; the default is asebahttp=http://127.0.0.1:3000 if VPL is served as a local file, or the same http server as the one serving VPL if it's served over http(s). For thymio-tdm, w=... specifies the url of the websocket (typically w=ws://ip:port), and pass=... the password (default: empty); the default is w=ws://localhost:8597, i.e. the Thymio Device Manager running locally with its default port. With a password, it could be w=ws://10.0.0.200:8597&pass=ABCDEF.
  • role: student (default), teacher (options to customize the user interface and vpl blocks), or teacher1 (options to customize only the vpl blocks).
  • ui: filename of the main json file (default ui.json)
  • uilanguage: 2-letter language code used to translate messages (default: en; otherwise, as defined in dictionary "i18n" of the user interface json file)
  • user: username displayed in the "vpl:filename" indicator (overrides window["vplUsername"])
  • shortcuts: true or false to override the default setting (default: true)
  • accessibility: list of accessibility features, separated by +. Default: none. Supported: "kbd" to edit vpl with keyboard.

Global variables

VPL is started by code in a "load" event listener defined in vpl-main.js. Some customization is possible using global variables. To avoid interferences with Google Closure Compiler, they are accessed as window["vplXXX"]. Here is a partial list:

  • window["vplApp"]: A3a.vpl.Application object
  • window["vplIsProgramChanged"]: function() to check if the vpl program has been changed since it has been loaded
  • window["vplGetProgramAsJSON"]: function(libAndUIOnly) to get vpl program as json, or block lib and UI configuration if libAndUIOnly is true
  • window["vplGetUIAsJSON"]: function() to get UI and block selection as json
  • window["vplQueryOptions"]: can be set to override the query string (what follows the question mark in the url); see section above for options.
  • window["vplCommandServer"]: can be set to an A3a.vpl.Com object to supervise the application
  • window["vplDisableResize"]: can be set to true to disable full-window mode
  • window["vplUsername"]: can be set to a string to display the username in "vpl:filename" indicator
  • window["vplUpload"]: can be set to a function(string filename, string json):void to implement the "vpl:upload" command
  • window["vplNextProgram"]: can be set to a function(string currentFilename, string? currentJsonProgram):nextJsonProgram to implement "vpl:nextProgram" command; if currentJsonProgram is null, just get a json containing a "filename" property for the next program; otherwise should save and return either actual program with "filename" property, or just object with "filename" property if the program is provided asynchronously; or null if nothing is available; when programs are available, should be cyclic
  • window["vplListenToCom"]: can be set to a function(msg):void to listen to messages sent by a supervisor application (teacher dashboard)
  • window["vplSendToCom"]: function(data):void to send a "client" message to a supervisor application (teacher dashboard)
  • window["vplStorageGetFunction"]: can be set to a void function(string filename, function(string jsonProgram, Object= options)) to get a file. Called at launch; if a program can be read (e.g. to restore a program saved to localStorage in a previous session), should call the function passed as 2nd argument with the json program and (optionally) a dictionary with the (optional) following entries: string "filename" (a filename which overrides the one passed to vplStorageGetFunction), boolean "readOnly" (true to make the program read-only), boolean "fixedFilename" (true to disable edutability of program filename; by default same as "readOnly"), boolean "customizationMode" (true to switch to ui customization mode like with command "vpl:teacher"), boolean "setAsNew" (true to use the program as the initial state after "vpl:new", like with command "vpl:teacher-setasnew")
  • window["vplUIRoot"]: url (relative to document) used to override location of ui.json to define UIROOT in about.html and help.html
  • window["vplSimMaps"]: "merged" for distinct maps (buttons "sim:map-kind" and "sim:map"), or comma-separated map names for merged maps (buttons "sim:map-height", "sim:map-ground", and/or "sim:map-obstacles"); default is "ground,height,obstacles"
  • window["vplConfig"]: can be set to configuration options: "ignoredCommands" is an array of command ids which are discarded and not available in the configuration mode
  • window["vplConvertToHTML"]: function(json, isVPL3UI) to convert the content of a .vpl3 (if isVPL3UI is false) or a .vpl3ui file (if isVPL3UI is true) to a static HTML file
  • window["vplConvertMDToHtml"]: function(md) to convert simple markdown to an html fragment (block-level elements such as h1, p, etc.)
  • window["vplTextFieldInputEvents"]: true to use input events of an invisible <input> element for text field input; false to use keydown events; default is true for Android, false for other platforms
  • window["vplConnections"]: dictionary of additional robot connection methods; keys are what's specified with query option robot and values are functions without argument which return an instance of a subclass of A3a.vpl.RunGlue