eboxy provides a simple scripting system for defining what should happen when an event occurs (eg., a button is pressed). Events for each type of object are defined in the Object Reference section.
To respond an event, you use the <event> tag within the body of the item you want to attach the event to. For example:
... <page ...> <event type="OnLoad"> echo "the page is loading" </event> <event type="OnShow"> # this is a comment echo "the page has been shown" echo "you can have as many commands as you like in a script" </event> ... <button ...> <event type="OnClick"> echo "button clicked" exec "ls -l" </event> <event type="OnGotFocus"> echo "button focused!" </event> </button> ... </page> ...
Since system events aren't associated with a page, they are kept in a separate section in the XML file - the system section. This must appear before the templates section (if it exists, otherwise before the pages section) and is optional. For example:
... <system> <event type="OnLoad"> echo "eboxy is loading" </event> ... </system> ... <pages> ... </pages>
Be warned that you will not get an error if the event you define a handler for does not exist - it will just never happen, so make sure you type the name correctly. Also, with buttons, there is a shortcut as you've already seen - if you only need to do something when the button is clicked, the <event type="onclick">...</event> is optional - if you wish, you can just put the script you want to run when the button is clicked inside the <button> tag body.
There is one other attribute to events, and that is the wait attribute. This tells eboxy whether the execution of the event should be threaded or not - in simple terms, whether eboxy should wait while your script runs or not. wait="false" by default if it is not specified, but you may wish to set it to true for some of your event scripts depending on the situation. Note that with wait="true" eboxy's GUI will effectively be frozen while your script runs, so this is not a good choice if your script will take a long time to run. Note: all system events and the page OnUnload event are always waited on - setting wait to false for these will have no effect.
The commands available to you in a script are as follows:
Table 4.1. Script Commands
|echo "text"||Prints the specified text on the standard output. Mainly for testing.|
|exec "command"||Runs the specified shell command. Control returns to the script immediately.|
|execwait "command"||Runs the specified shell command, and waits until it has finished executing.|
|exechide "command"||Runs the specified shell command, hiding the GUI while the program executes.|
|page pagename||Jump to the page specified by pagename. (This corresponds to the name attribute for the page). Note the lack of quotes - this is intentional, because pages are objects.|
|load "filename"||Loads the XML file specified by filename. Note that all pages from the current file are purged from memory at this point, so you'll need to load the old file again if you want to jump back.|
|loadplugin "plugin"||Loads a plugin. More about plugins in the Plugins section|
|delay "x"||Wait for a specified number of milliseconds (1000ms = 1 second)|
There are two other commands in addition to those above - the function version of execwait, and execwaitcapture. These will be described below.
You may also put in comments - any line that starts with a # will be ignored. Also, whitespace at the start of a line is ignored.
You may set the values of properties on any widget in the system (including those on other pages, as names are unique system-wide). For example:
button1.caption = "new"
This means the widgets you want to refer to must be named (ie, have a name attribute assuming they are created from within the XML file). Certain properties are read-only.
eboxy scripts know about strings, integer numbers, and boolean literals (true and false) and most of the time these can be used interchangeably. As you have seen, strings must be enclosed in quotes. Colours are represented as specially formatted strings - eg. to change the colour of a label's text, you'd do the following:
label5.fontcolor = "#13F6CA"
Anywhere you can specify a value, you may instead specify an expression. Expressions are built up of other strings and/or numbers. You may use property values and variables (more on that below) in expressions as well. For example:
button1.caption = "Activate " + label1.caption label5.caption = "X " + label2.caption + " X" something = (1 + 5) / 2 * 3
As you may have noticed, the + operator has a double purpose - it is used for addition of numbers and concatenating strings together. The rule is, if one or both of the two things either side of the + symbol is a string, then a string concatenation is performed, otherwise the two are both numbers and will be added together numerically. The other arithmetic operators (-, *, /, %, ^) and the numeric conditional operators (>, <, >=, <=) convert their arguments to a number first before operating. Note that you can use the latter in order to work around the former if you need to: say you have obtained a number from somewhere, except it came in as a string (say, the value of the text property of a textfield). Just subtract zero from the string and it will be converted to a number. For example, "1" + 5 results in 15 as a string, whereas ("1" - 0) + 5 results in 6 as a number.
The order of operations in expressions is generally what you'd expect, but you can make use of brackets ( ) to control it if you need to. Sometimes you may wish to put in extra brackets to make it clear what you are doing.
You may include special characters in strings by using a backslash. The special characters you can use are:
eboxy's scripting language supports the most commonly-used boolean operators (and, or, not, xor) and comparison operators (==, !=, >, <, >=, <=), and the boolean literals true and false are allowed. This allows you to perform some rudimentary conditional operations. For example:
button1.enabled = label1.text == "hello" and not checkbox1.checked button2.enabled = true
Note that the equality operator == is distinct from the assignment operator =. Fortunately, unlike some other languages the assignment operator is not allowed in any situations where it could be confused with the equality operator, and attempting to use it as such will result in an error.
Unfortunately, because the scripts are in an XML file, you need to encode the > and < characters as > and < when using them in the comparison operators. For example:
echo 72 > 78 echo 44 <= 30
Alternatively, you can enclose your script in an XML standard CDATA section and then use the characters as normal. A CDATA section starts with <![CDATA[ and ends with ]]>. For example
<![CDATA[ echo 72 > 78 echo 44 <= 30 ]]>
You can't mix the two however - inside a CDATA section, the < and > entities will not be expanded and you will get a script error.
Some object types have methods. Buttons have a single method, "click", which you can invoke like this:
This does the same as if the button was clicked by the user. Note that the brackets on the end are actually optional if you are just calling the method and aren't passing any parameters to the method, however you should always put them in for clarity. Some methods take parameters, for instance the additem method of a listbox widget:
mylist.additem("this is a list item")
Methods are also capable of returning values, and taking multiple arguments. Multiple arguments are separated by commas. No methods exist in eboxy's standard widgets that returns a value, but it is possible to build one into a plugin. An example of using such a method would be:
echo anobject.testmethod(15, "example")
There are a few "special" objects that you can refer to in scripts. The first is system, which provides access to a few global functions. The other two special objects are really just references - currentpage refers to the currently visible page and focusedwidget refers to the currently focused widget. You can use these as if they were the objects themselves, for example:
eboxy's scripting language has support for variables. All you need to do is assign a value to a variable to begin using it. You can assign any expression to a variable. Once a variable has been assigned you can use it anywhere an expression is accepted, and its value will be substituted in.
myvariable = "hello" anumber = 5 echo myvariable echo anumber + 2
Note that unlike shell scripts, attempting to refer to a variable which you have not previously assigned a value to will result in an error - this is because the variable won't actually exist. Most of the time eboxy's scripting language does not care whether a string or a number is supplied, and variables do not externally have any particular type (although internally they do - but you don't need to worry about this most of the time). This is known as a "loosely-typed" language, and it keeps things simple. Currently, variables are always globally available once assigned, and exist until eboxy quits (this may change in future). The rules for variable naming are the same as for widgets.
If you wish to get something back from an executed program, you will need to use these commands. Both of them wait while the program executes, and return only when it finishes. execwait() returns the result code from the program (usually 0 unless an error occurred) and execwaitcapture() returns the output of the program as a string (and does not print it to the terminal, unlike all of the other exec* commands).
resultcode = execwait("someprocess") button1.enabled = (resultcode == 0) dirsize = execwaitcapture("du -sh /mnt/files/incoming | cut -f 1") label1.caption = dirsize
In the above example, two things are done. First it runs the command "someprocess", and if it ran successfully then button1 is enabled. Next, it gets the total size of the /mnt/files/incoming directory in human readable format and displays it in label1.
eboxy scripts are fairly simple. They do not provide conditional statements or loops, or support floating point numbers. This is partially because they aren't meant to be used for general programming - they are mainly for simple control of and interaction with plugins; but also because the current code is not capable of any kind of jumps (which are required for conditional statements, loops etc) and would require substantial changes to do so. If you need to do more than the scripting system allows, you should probably consider writing a plugin to do what you want. See the Plugins section.
You can bind user actions directly to buttons. However, sometimes you may want to be able to respond to an action without showing a button on the screen. To do this you need to use an actionhandler. Actionhandlers can be global (always active) or local (specific to a page), depending on where they appear in the XML file. A local actionhandler will always override a global one with the same action.
To define an actionhandler, add the following to the XML file:
<actionhandler action="actionname"> # put your script code to be run here </actionhandler>
To make this a local action, include it within the element for the page in which you wish it to be active. To make it global, include it within the system section.