Livecode Wiki
Advertisement
Warning Warning

The following topics are only for very skilled livecode programmers, not for beginners. The majority of livecoders doesn't need to know how to code widgets, they can use group.

A widget is a new control inside the IDE, instead of using groups of existing controls, you can create your custom control with you properties and share it with other livecode programmers. The advantage is that you can ungroup or accidentally modify it. Keeping easier to set properties and values. Moreover you can use other programming function, for example from Java or C.

Widgets are only for very expert livecode developers. All other user can work without knowing widget creations. Continue to read this page only if you are an expert livecode developer.

Before continue, see read this LCB Guide

If you are familiar with widget, you can read the widget dictionary.

Widgets ready to use in LiveCode

Introduction[]

LiveCode Builder is a variant of the current LiveCode scripting language (LiveCode Script) which has been designed for 'systems' building.

It is statically compiled with optional static typing and direct foreign code interconnect (allowing easy access to APIs written in other languages).

Unlike most languages, LiveCode Builder has been designed around the idea of extensible syntax. Indeed, the core language is very small - comprising declarations and control structures - with the majority of the language syntax and functionality being defined in modules.

The syntax will be familiar to anyone familiar with LiveCode Script, however LiveCode Builder is a great deal more strict - the reason being it is intended that it will eventually be compilable to machine code with the performance and efficiency you'd expect from any 'traditional' programming language. Indeed, over time we hope to move the majority of implementation of the whole LiveCode system over to being written in LiveCode Builder.

One of the principal differences is that type conversion is strict, there is no automatic conversion between different types such as between number and string. Such conversion must be explicitly specified using syntax (currently this is using things like

... parsed as number 

and

... formatted as string

Tokens[]

The structure of tokens is similar to LiveCode Script, but again a little stricter. The regular expressions describing the tokens are as follows:

  • Identifier: [A-Za-z_][A-Za-z0-9_.]*
  • Integer: [0-9]+
  • Binary Integer: 0b[01]+
  • Hexadecimal Integer: 0x[0-9a-fA-F]+
  • Real: [0-9]+"."[0-9]+([eE][-+]?[0-9]+)?
  • String: "[^\n\r"]*"
  • Separator: Any whitespace containing at least one newline

Strings use backslash ('\') as an escape - the following are understood:

  • \n: LF (ASCII 10)
  • \r: CR (ASCII 13)
  • \t: TAB (ASCII 9)
  • \q: double quote '"'
  • \u{X...X}: character with unicode codepoint U+X...X - any number of nibbles may be specified, but any values greater than 0x10FFFF will be replaced by U+FFFD.
  • \\: backslash '\'

Source files are presumed to be in UTF-8 encoding.

Comments[]

LiveCode Builder supports single line comments, which begin with `//` or `--` and extend to the end of the line. There are also block comments, which begin with `/*` and end with `*/`, and can span multiple lines.

  • Single-line comment: (--|//)[^\n\r]*
  • Block comment**: /\*([^*](\*[^/])?)*\*/

A block comment that spans multiple lines terminates the line of code that it begins on.

Line continuation[]

A LiveCode builder statement or declaration can be continued onto multiple lines of code by placing the line continuation character `\` at the end each line.

  • Line continuation**: \\(\n|\r\n|\r)

A line continuation cannot occur within a comment.

Case-Sensitivity[]

At the moment, due to the nature of the parser being used, keywords are all case-sensitive and reserved. The result of this is that, using all lower-case identifiers for names of definitions should be avoided. However, other identifiers case-insensitive - so a variable with name pFoo can also be referenced as PFOO, PfOO, pfoO etc.

The current parser and syntax rules for LiveCode Builder uses bison (https://www.gnu.org/software/bison/ ). Unfortunately, this means that any keywords have to be reserved as the parser cannot distinguish the use of an identifier in context (whether it is a keyword at a particular point, or a name of a definition).

It is highly recommended that the following naming conventions be used for identifiers:

  • tVar - for local variables
  • pVar - for in parameterns
  • rVar - for out parameters
  • xVar - for inout parameters
  • mVar - for global variables in widgets
  • sVar - for global variables in libraries
  • kConstant - for constants
  • Use identifiers starting with an uppercase letter for handler and type names.

By following this convention, there will not be any ambiguity between identifiers and keywords. (All keywords are all lower-case).

Typing[]

LiveCode Builder is a typed language, although typing is completely optional in most places (the only exception being in foreign handler declarations). If a type annotation is not specified it is simply taken to be the most general type *optional any* (meaning any value, including nothing).

The range of core types is relatively small, comprising the following:

  • nothing: the single value nothing
  • Boolean: one of true or false
  • Integer: any integral numeric value (size limitations apply)
  • Real: any numeric value (size and accuracy limitations apply)
  • Number: any integer or real value
  • String: a sequence of UTF-16 code units
  • Data: a sequence of bytes
  • List: a sequence of any values
  • Array: a mapping from strings to values
  • any: a value of any type

Additionally, all types can be annotated with **optional**. An optional annotation means the value may be the original type or nothing.

The current compiler does not do type-checking; all type-checking happens at runtime. However, this is being worked on so there will soon be a compiler which will give you type errors at compile-time.

Modules[]

Syntax

module <Name> 
  { ( Definition | Metadata | Import ) }
  { ( Definition | Metadata | Import ) }
  ...
end module

The smallest compilable unit of LiveCode Builder is the module. Each module is uniquely named using reverse DNS notation, and the names of modules are considered to live in a global namespace.

A module is a collection of public and private definitions, including constants, variables, types and handlers.

A module may depend on another module through import. An imported modules public definitions become accessible to the importing module.

For integration with the existing LiveCode system, there are two module variants which may be used. Widgets (use widget instead of module) and Libraries (use library instead of module). A widget appears in LiveCode as a control, whilst a library adds all its public handlers to the bottom of the message path.

Usually a widget is like this:

widget com.livecode.extensions.myWidget
   ....#here all needed to create a widget
end widget

Metadata[]

Syntax:

metadata <Name>  is <Value>

The metadata clauses allow a set of key-values to be encoded in the compiled module. These are not used in compilation or execution, but may be used by the system loading and using the module.

At the moment, the following keys are understood:

  • title: a human-readable name for the module
  • description: a simple description of the module's purpose
  • version: a string in the form X.Y.Z (with X, Y and Z integers) describing the modules version
  • author: the name of the author of the module

Example:

widget com.livecode.extensions.myWidget
  metadata title is "My Super cool widget"
  metadata author is "John Connor"
  ...
end widget

Imports[]

Syntax:

use <Name>

The use clauses allow a module to refer to another module by importing all the target module's public definitions into its namespace.

The name of the module specified must be its full name, for example:

use com.livecode.canvas.xxx

A module may use any other module, as long as doing so does not cause a cycle in the dependency graph.

Example:

widget com.livecode.extensions.myWidget
 metadata title is "My Super cool widget"
 metadata author is "John Connor"  
 use com.livecode.canvas
 use com.livecode.widget
 use com.livecode.engine
 ...
end widget

Modules list[]

  • com.livecode.canvas Provides the syntax and types for 2D drawing allowing developers to draw to a canvas. Required if creating a widget.
  • com.livecode.widget Contains syntax specific to widget building such as "my width" and "the mouse position".
  • com.livecode.engine Contains syntax for all extension building such as "dispatch" and "log".
  • com.livecode.arithmetic Contains syntax for basic mathematical operations.
  • com.livecode.array Contains syntax for operations on arrays.
  • come.livecode.assert Debug library
  • com.livecode.binary Contains syntax for operations on binary data.
  • com.livecode.bitwise Contains syntax for bitwise logical operators.
  • com.livecode.byte Contains syntax for operations on byte chunks.
  • com.livecode.char Contains syntax for operations on char chunks.
  • com.livecode.codeunit Contains syntax for operations on codeunit chunks.
  • com.livecode.date Contains syntax for accessing the date and time.
  • com.livecode.file Contains syntax for file I/O operations.
  • com.livecode.foreign Provides the type bindings for foreign types.
  • com.livecode.list Contains syntax for operations on lists.
  • com.livecode.logic Contains syntax for logical operators.
  • com.livecode.mathfoundation Contains syntax for foundational mathematical operations.
  • com.livecode.math Contains syntax for mathematical operations.
  • com.livecode.sort Contains syntax for sorting operations.
  • com.livecode.stream Contains syntax for stream I/O operations.
  • com.livecode.string Contains syntax for operations on strings.
  • com.livecode.system Contains syntax for accessing system information.
  • com.livecode.type Contains syntax for general operations on types.
  • com.livecode.typeconvert Contains syntax for conversions between types.
  • com.livecode.unittest Contains syntax for unit testing LiveCode Builder programs.

Definitions[]

Syntax:

(public) ConstantDefinition
(public) TypeDefinition
(public) HandlerTypeDefinition
(public) VariableDefinition
(public) HandlerDefinition
(public) ForeignHandlerDefinition
PropertyDefinition
EventDefinition

Definitions are what are used to define usable entities in the language. All definitions are named using a unique identifier (so you cannot have two definitions with the same name).

Definitions can be either public or private (the default is private, so there is no need to explicitly specify that). Public definitions are available when the module is used by another module whereas private definitions can only be used within the module.

Properties and events are, by their nature, always public as they define things which only make sense to access from outside.

When writing a library module, all public handlers are added to bottom of the message path in LiveCode Script.

Constants[]

Syntax:

constant <Name> is <Value>

A constant definition defines a named constant. The value can be any expression which depends on only on constant values to evaluate.

Constants are not currently implemented, although the syntax is recognised.

Usally constant names starts with k.

Example:

widget com.livecode.extensions.myWidget
metadata title is "My Super cool widget"
metadata author is "John Connor"  
use com.livecode.canvas
use com.livecode.widget
use com.livecode.engine
constant kSpeed is 20
...

end widget

Types[]

Syntax:

type <Name> is <TypeOf>

A type definition defines an alias, it names the given type with the given Name, allowing the name to be used instead of the type.

A type clause describes the kind of value which can be used in a variable or parameter.

If a type is an identifier, then this is taken to be a named type defined in a type definition clause.

An optional type means the value can be either the specified type or nothing. Variables which are of optional type are automatically initial zed to nothing.

The remaining types are as follows:

  • any: any value
  • Boolean: a boolean value, either the value true or false.
  • Integer: any integer number value
  • Real: any real number value
  • Number: any number value
  • String: a sequence of UTF-16 code units
  • Data: a sequence of bytes
  • Array: a map from string to any value (i.e. an associative array, just like in LiveCode Script)
  • List: a sequence of any value
  • nothing: a single value *nothing* (this is used to describe handlers with no return value - i.e. void)
  • Pointer: a low-level pointer (this is used with foreign code interconnect and shouldn't be generally used).

Integer and Real are currently the same as Number.

Example:

widget com.livecode.extensions.myWidget
 metadata title is "My Super cool widget"
 metadata author is "John Connor"  
 use com.livecode.canvas
 use com.livecode.widget
 use com.livecode.engine
 constant kLeft is 20
 type myType is number
 type myType is optional string
 ...
end widget

Handler Types[]

Syntax:

[ foreign ] handler type <Name> ( [ ParameterList ] ) [returns <ReturnType ]

A handler type definition defines a type which can hold a handler. Variables of such types can hold handlers (just like function pointers in C) which allows them to be called dynamically.

If the handler type is defined as foreign then automatic bridging to a C function pointer will occur when the type appears as the type of a parameter in a foreign handler definition.

Passing an LCB handler to a foreign function requires creation of a function pointer. The lifetime of the function pointer is the same as the widget or module which created it.

Variables[]

Syntax

variable <Name> [ as <TypeOf> ]

A variable definition defines a module-scope variable. In a widget module, such variables are per-widget (i.e. instance variables). In a library module, there is only a single instance (i.e. a private global variable).

The type specification for the variable is optional, if it is not specified the type of the variable is optional any meaning that it can hold any value, including being nothing.

Variables whose type has a default value are initialized to that value at the point of definition. The default values for the standard types are:

  • optional: nothing
  • Boolean: false
  • Integer: 0
  • Real: 0.0
  • Number: 0
  • String: the empty string
  • Data: the empty data
  • Array: the empty array
  • List: the empty list
  • nothing: nothing

Variables whose type do not have a default value will remain unassigned and it is a checked runtime error to fetch from such variables until they are assigned a value.

Example:

widget com.livecode.extensions.myWidget
 metadata title is "My Super cool widget"
 use com.livecode.engine
 constant kLeft is 20
 variable tX as Integer
 ...
end widget

Handlers[]

Syntax:

[unsafe] handler <Name> ([ParameterList]) [ returns <ReturnType>]
              { Statement }
     end handler

Handler definitions are used to define functions which can be called from LiveCode Builder code, invoked as a result of events triggering in a widget module, or called from LiveCode Script if public and inside a library module.

There is no distinction between handlers which return a value and ones which do not, apart from the return type. Handlers can be called either in expression context, or in statement context. If a handler which returns no value (it is specified as returns nothing) is called in expression context then its value is nothing.

The parameter is a list of variables separated by comma:

Parameter1,parameter2,..

each parameter:

( in | out | inout ) <Name> [ as <ParamType>]

The parameter list describes the parameters which can be passed to the handler. Handlers must be called with the correct number of parameters, using expressions which are appropriate to the mode.

An in parameter means that the value from the caller is copied to the parameter variable in the callee handler.

An out parameter means that no value is copied from the caller, and the value on exit of the callee handler is copied back to the caller on return.

It is a checked runtime error to return from a handler without ensuring all non-optional 'out' parameters have been assigned a value. However, this will only occur for typed variables whose type does not have a default value as those which do will be default initialized at the start of the handler.

An inout parameter means that the value from the caller is copied to the parameter variable in the callee handler on entry, and copied back out again on exit.

The type of parameter is optional, if no type is specified it is taken to be optional any meaning it can be of any type.

Only assignable expressions can be passed as arguments to inout or out parameters. It is a checked compile-time error to pass a non-assignable expression to such a parameter.

If 'unsafe' is specified for the handler, then the handler itself is considered to be unsafe, and may only be called from other unsafe handlers or unsafe statement blocks.

Example:

widget com.livecode.extensions.myWidget
 metadata title is "My Super cool widget"
 use com.livecode.engine
 constant kLeft is 20
 handler OnSave(out rProperties as Array)
   put the empty array into rProperties
 end handler
 ...
end widget

Foreign Handlers[]

Syntax:

foreign handler <Name> ( [ ParameterList ] ) [ returns <ReturnType> ) ]  'binds' 'to' <Binding>

ReturnType can be:

  • CBool
  • CInt
  • CUInt
  • CFloat
  • CDouble

A foreign handler definition binds an identifier to a handler defined in foreign code.

Foreign handler definitions can contain more types in their parameters than elsewhere - those specified in the ForeignType clause. These allow low-level types to be specified making it easier to interoperate.

Foreign types map to high-level types as follows:

  • bool maps to boolean
  • int and uint map to integer (number)
  • float and double map to real (number)

This mapping means that a foreign handler with a bool parameter say, will accept a boolean from LiveCode Builder code when called.

At present, only C binding is allowed and follow these rules:

  • any type passes an MCValueRef
  • nothing type passes as the null pointer
  • Boolean type passes an MCBooleanRef
  • Integer type passes an MCNumberRef
  • Real type passes an MCNumberRef
  • Number type passes an MCNumberRef
  • String type passes an MCStringRef
  • Data type passes an MCDataRef
  • Array type passes an MCArrayRef
  • List type passes an MCProperListRef
  • Pointer type passes a void
  • CBool type passes a bool (i.e. an int - pre-C99).
  • CInt type passes an int
  • CUInt type passes an unsigned int
  • CFloat type passes a float
  • CDouble type passes a double

Modes map as follows:

  • in mode is just pass by value
  • out mode passes a pointer to a variable of one of the above types, the variable is uninitialized on entry
  • inout mode passes a pointer to a variable of one of the above types, the variable is initialized to a value on entry

If the return type is of a Ref type, then it must be a copy.

If an out parameter is of a Ref type, then it must be a copy (on exit)

If an inout parameter is of a Ref type, then its existing value must be released, and replaced by a copy (on exit).

The binding string for foreign handlers has the following form:

   [lang:][library>][class.]function[!calling]

where

  • lang specifies the language (must be 'c' at the moment)
  • library specifies the name of the library to bind to (if no library is specified a symbol from the engine executable is assumed).
  • class is currently unused.
  • function specifies the name of the function symbol to bind to (on Windows, the symbol must be unadorned, and so exported from the library by listing it in a DEF module).
  • calling specifies the calling convention which can be one of:
    • default
    • stdcall
    • thiscall
    • fastcall
    • cdecl
    • pascal
    • register

All but 'default' are Win32-only, and on Win32 'default' maps to 'cdecl'. If a Win32-only calling convention is specified on a non-Windows platform then it is taken to be 'default'.

Foreign handler's bound symbols are resolved on first use and an error is thrown if the symbol cannot be found.

Foreign handlers are always considered unsafe, and thus may only be called from unsafe context - i.e. from within an unsafe handler, or unsafe statement block.

Example:

use com.livecode.foreign
foreign handler MCStringEncode(in Source as String, in Encoding as CInt, in IsExternalRep as CBool, out Encoded as Data) returns CBool binds to "<builtin>"

Properties[]

Syntax

property <Name> get <Getter> [ set <Setter> ]

Property definitions can only appear in widget modules. They define a property which can be accessed from LiveCode Script in the usual way:

the myProperty of widget 1

The following properties are livecode internal and always added by livecode, so you don't have to specify inside the widget:

  • name
  • tooltip
  • visible
  • disabled

Both getter and setter clauses can use either a variable or handler identifier. If a variable identifier is used, then the property value is fetched (and stored) from that variable. If a handler identifier is used then a handler is called instead.

A getter handler must take no arguments and return a value. A setter handler must take a single argument and return no value.

The set clause is optional. If it is not present then the property is read-only. Set is the name of the handler, not a variable.

Example

property chartData get getChartData set setChartData

Property Inspector[]

If you want that developer can set properties with the Property Inspector, you have to set the metadata of propertyName.editor to the library com.livecode.pi and set the metadata editor, options, default, label. Fore example:

property widgetTheme get mWidgetTheme set setWidgetTheme
metadata widgetTheme.editor is "com.livecode.pi.enum"
metadata widgetTheme.options is "iOS,Android(Dark),Android(Light)"
metadata widgetTheme.default is "iOS"
metadata widgetTheme.label is "Widget Theme"

This is the result:

SwitchButton1

The available visual editors are:

  • com.livecode.pi.boolean
  • com.livecode.pi.color
  • com.livecode.pi.colorwithalpha
  • com.livecode.pi.customprops
  • com.livecode.pi.decorations
  • com.livecode.pi.enum
  • com.livecode.pi.file
  • com.livecode.pi.font
  • com.livecode.pi.gradient
  • com.livecode.pi.gradientramp
  • com.livecode.pi.graphicEffect
  • com.livecode.pi.imageID
  • com.livecode.pi.image_id
  • com.livecode.pi.imageid
  • com.livecode.pi.integer
  • com.livecode.pi.number
  • com.livecode.pi.pattern
  • com.livecode.pi.point
  • com.livecode.pi.propertyProfile
  • com.livecode.pi.script
  • com.livecode.pi.stackfiles
  • com.livecode.pi.string
  • com.livecode.pi.styledText
  • com.livecode.pi.text
  • com.livecode.pi.textalign
  • com.livecode.pi.textstyle

Events[]

Syntax:

event <Name> ( [ParameterList] ) [ as <ReturnType> ]

Event definitions define a callable handler which calls back to the environment.

Whilst events can be defined they currently cannot be used. To send a message to the LiveCode Script environment use the dispatch command which allows sending messages to arbitrary LiveCode Script objects.

Statements[]

There are a number of built-in statements which define control flow, variables, and basic variable transfer. The remaining syntax for statement is defined in auxiliary modules.

Variable Statements[]

Syntax:

variable <Name> [ as <TypeOf> ]

A variable statement defines a handler-scope variable. Such variables can be used after the variable statement and up to the end of the current statement block, but not before.

Variables whose type have a default value are initialized with that value at the point of definition in the handler. See the main Variables section for the defaults of the standard types.

It is a checked runtime error to attempt to use a variable whose type has no default before it is assigned a value.

The type specification for the variable is optional, if it is not specified the type of the variable is optional any meaning that it can hold any value, including being nothing.

If Statements[]

Syntax

if <Condition> then
             { Statement }
           [ { else if <Condition> then
               { Statement } ]
           [ else
               { Statement } ]
           end if

The if statement enables conditional execution based on the result of an expression which evaluates to a boolean. Like in standard livecode.

Each block of code in an if/else if/else statement defines a unique scope for handler-local variable definitions.

It is a checked runtime error to use an expression which does not evaluate to a boolean in any condition expression.

Repeat Statements[]

Syntax:

  repeat  [forever | <Count> times | while <Condition> | until <Condition> | with <Counter> from ( up | down ) to <Finish> [ by <Step>] | for each <Iterator> in <Container>
  ...
  [next repeat]
  [exit repeat]
  ...
  end repeat

The repeat statements allow iterative execute of a sequence of statements.

The block of code present in a repeat statement defines a unique scope for handler-local variable definitions.

The repeat forever form repeats the body continually. To exit the loop, either an error must be thrown, or exit repeat must be executed.

The repeat times form repeats the body Count number times. If Count evaluates to a negative integer, it is taken to be zero.

The repeat while form repeats the body until the Condition expression evaluates to false.

The repeat until form repeats the body until the Condition expression evaluates to true.

The repeat with form repeats the body until the Counter variable reaches or crosses (depending on iteration direction) the value of the Finish expression. The counter variable is adjusted by the value of the Step expression on each iteration. The start, finish and step expressions are evaluated before the loop starts and are not re-evaluated. The Counter variable must be declared before the repeat statement.

The repeat for each form evaluates the Container expression, and then iterates through it in a custom manner depending on the Iterator syntax. For example:

   repeat for each char tChar in "abcdef"
     -- do something with tChar
   end repeat

The next repeat statement terminates the current iteration of the enclosing loop and starts the next iteration of the loop, or exits if currently on the last iteration.

The exit repeat statement terminates the current iteration of the enclosing loop, continuing execution at the statement after the enclosing loop's end repeat.

Throw Statements[]

Syntax

throw <Error>

The throw statement causes an error to be raised. This causes execution to terminate, and the error is passed back to environment.

The Error expression must be an expression that evaluates to a string.

There is currently no try or catch mechanism in LiveCode Builder, so throwing an error will cause the error to be raised in LiveCode Script in the appropriate context.

Return Statements[]

Synatx:

return [ <Value> ]

The return statement causes execution of the current handler to end, and control return to the caller.

If a Value expression is specified, it is evaluated and returned as the result of the handler call.

It is a checked runtime error for a value returned from a handler to not match the return type of the handler it is in.

Transfer Statements[]

Syntax:

put <Value> into <Target>
set <Target> to <Value>
get <Value>

The put and set statements evaluate the Value expression and assign the resulting value to the Target expression.

The target expression must be assignable.

It is a checked runtime error for the source value's type to not be compatible with the target expression's type.

The get statement evaluates the Value expression and returns it as the result of the statement. The value is subsequently available by using the result expression.

Call Statements[]

Syntax:

<Handler> ( [ <Arguments] )

The call statement executes a handler with the given arguments.

The Handler identifier must be bound to either a handler or foreign handler definition.

The Arguments are evaluated from left to right and passed as parameters to the variable.

It is a checked runtime error for the types of 'in' and 'inout' arguments to not match the declared types of the handler's parameters.

Any parameters of 'out' type are not evaluated on entry, but assigned to on exit.

Any parameters of 'inout' type are evaluated on entry, and assigned on exit.

It is a checked compile-time error to pass non-assignable expressions to parameters which are of either 'out' or 'inout' type.

The return value of a handler is subsequently available by using the result expression.

All handlers return a value, even if it is nothing. This means that calling a handler will always change the result.

Bytecode Statements[]

Syntax:

bytecode
  { BytecodeOperation }
end

the bytecodeOperation has this syntax:

<Label> :  'register' <Name> [ 'as' <Type> ] | <Opcode> { BytecodeArgument , ',' }

The bytecode statement allows bytecode to be written directly for the LiveCode Builder Virtual Machine.

Bytecode operation arguments can either be a constant expression, the name of a definition in current scope, the name of a register, or the name of a label in the current bytecode block. The exact opcodes and allowed arguments are defined in the LiveCode Builder Bytecode Reference.

Labels are local to the current bytecode block, and can be used as the target of one of the jump instructions.

Register definitions define a named register which is local to the current bytecode block. Registers are the same as handler-local variables except that they do not undergo default initialization.

Bytecode statements are considered to be unsafe and can only appear inside unsafe handlers or unsafe statement blocks.

Bytecode blocks are not intended for general use and the actual available operations are subject to change.

Unsafe Statements[]

Syntax:

unsafe
  { Statement }
end unsafe

The unsafe statement allows a block of unsafe code to be written in a safe context.

In particular, calls to unsafe handlers (including all foreign handlers) and bytecode blocks are allowed in unsafe statement blocks but nowhere else.

Expressions[]

There are a number of expressions which are built-in and allow constant values, access to call results, list construction and calls. The remaining syntax for expressions is defined in auxiliary modules.

Constant Value Expressions[]

Constant value expressions evaluate to the specified constant value.

The nothing expression evaluates to the nothing value and can be assigned to any optional typed variable.

The true and false expressions evaluate to boolean values.

The INTEGER and REAL expressions evaluate to numeric values.

The STRING expression evaluates to a string value.

Constant value expressions are not assignable.

Variable Expressions[]

Variable expressions evaluate to the value of the specified variable.

Variable expressions are assignable.

Result Expressions[]

the result

The result expression evaluates to the return value of the previous (executed) non-control structure statement.

Result expressions are not assignable.

List Expressions[]

A list expression evaluates all the elements in the expression list from left to right and constructs a list value with them as elements.

The elements list is optional, so the empty list can be specified as

[]

List expressions are not assignable.

Array Expressions[]

An array expression evaluates all of the key and value expressions from left to right, and constructs an **Array** value as appropriate. Each key expression must evaluate to a **String**.

The contents are optional, so the empty array can be written as `{}`.

Array expressions are not assignable.

Call Expressions[]

A call expression executes a handler.

Its use is identical to a call statement, except that the return value of the handler is the value of the expression, rather than being available as the result.

Handlers which return no value (i.e. have nothing as their result type) can still be used in call expressions. In this case the value of the call is nothing.

Foreign bindings to Java[]

See Foreign bindings to Java

Main messages[]

OnSave[]

The OnSave message is used when you save your script or stack, and the widget must save some data, for example its properties. Usually the properties should be saved in the array rProperties:

Example:

public handler OnSave(out rProperties as Array)
  put the empty array into rProperties
  put mWidgetTheme into rProperties["widgetTheme"]
  put mColorScheme into rProperties["colorScheme"]
  put mSwitchIsOn into rProperties["checked"]
end handler

OnLoad[]

The OnLoad message is used when you load your script or stack, and the widget must load some data, for example its properties. Usually the properties should be loaded from the array pProperties:

Example:

public handler OnLoad(in pProperties as Array)
 put pProperties["widgetTheme"] into mWidgetTheme
 put pProperties["colorScheme"] into mColorScheme
 put pProperties["checked"] into mSwitchIsOn
end handler

OnCreate[]

The OnLoad message is used when the widget is created or inserted in the stack. It usually should return nothing.

Example:

public handler OnCreate() returns nothing
  put "iOS" into mWidgetTheme
  put the empty string into mColorScheme
  put false into mSwitchIsOn
  fetchAndroidColors()
  updateVariables()
end handler

OnPaint[]

Message sent when the widget is to be drawn or redraw. It's wise to always write an OnPaint handler.

Example:

public handler OnPaint()
 variable tCirclePath as Path
 put circle path centered at point [the width of my bounds/2,the height of my bounds/2] with radius (the width of my bounds/2) into tFacePath
 set the paint of this canvas to solid paint with color [1, 0, 1]
 fill tFacePath on this canvas
end handler
Advertisement