Contents |
You can find the online WidSets API documentation here.
See the image for the idea behind the WSL concept.
Comments
/* comment here*/ // another comment
Literals
; // line ends ”lorem ipsum” /* string */ ’\n’ /* character, produces int */ 123456 /* integer */ 0777777 /* octal */ 0xcafebabe /* hexa */ 0b101010101 /* binary */
Statements
if else while do for switch case default return break continue foreach [Java5]
Operators
+ - * / % & | ^ << >> += -= *= /= %= &= |= ^= <<= >>= < <= > >= == != ! && || ++ -- ~ instanceof new ?:
No access qualifiers
public protected private static synchronized abstract transient volatile native strictfp
No user defined classes
No import
No exception handling
No floating points
No language level support for Java-style array[] syntax
ByteArray init_rc4(ByteArray key)
{
ByteArray perm = new ByteArray(256);
for(int i=0; i<256; i++) {
perm[i] = i;
}
int j = 0;
for(int i=0; i<256; i++) {
j = (j + perm[i] + key[i % key.length()]) & 0xff;
perm[i], perm[j] = perm[j], perm[i];
}
return perm;
}
Flow-control statements break and continue do not support labels
Limited set of primitive types:
boolean char int long
Local variables must be introduced with an assignment
void test()
{
int j; /* error, missing assigment */
{
int c = 0;
}
{
int d = c; /* error, 'c' is not visible here */
}
}
Widget variables can be left unassigned.
class
{
Object foo;
void test()
{
if (foo == null) {
printf("It's null allright");
}
}
}
Shell style comments
# crazy thunk
Binary literals
int i = 0b101010101;
XOR operator: ^^
Constants – with primitive and String types
const int MAX = 100; const String PASSWORD = "n00Bh2xöR";
Typedef - type definition
typedef int Arithmetic(int a, int b);
int add(final int a, final int b)
{
return a+b;
}
void test()
{
Arithmetic a = add;
int c = a(10, 20); // -> not needed
}
boolean break case class const continue default do else false for foreach if instanceof int long new null return struct switch true void while
Primitives
boolean /* true/false */ char /* character */ int /* signed 32 bit */ long /* signed 64 bit */
Boolean is internally handled as int.
Any classes declared on API
Implicit casting occurs if possible.
Any primitive converts to any other primitive
Explicit casting is different
Object f = ...; Gizmo g = Gizmo(f); /* whoa, looks like an function call */ boolean b = ...; int zeroOrOne = int(b);
Benefit of this syntax is reduced noise and chaining:
Object f = ...; int length = String(f).length(); /* ugly java style: ((String)f).length(); */
On assignments, super type is promoted to sub type automatically
Object a = ...; String b = a; /* yep, that’s right ! */
Contrary to Java, the casting is purely a compile time feature
List a = new List(); Object b = a; String c = String(b); int i = c.length(); /* Croak! ClassCastException */
NullPointerException has similar sematics as well.
On the previous example, this is what happens
/* byte code */
aload $1 /* b */
astore $2 /* c */
pop
aload $2 /* c */
invoke_native1 #40 /* int String.length() */
/* jump to Java */
public int invoke(int sp, int[] istack, Object[] astack, long[] lstack, int method) {
switch(method) {
case 40:
/* int String.length() */
istack[sp] = ((String)astack[sp]).length(); /* Croak! ClassCastException */
return 0;
}
}
When selecting target method for invocation, all arguments are checked.
There are four match categories:
Result of argument list is equal to the ”worst” match. If there are multiple matches on same category, ambiguity is presented as to user. However, the resolution is quite natural - only some rare situations require explicit casts
String, int getNameAndAge() {
return "John", 27;
}
int, int sort(int a, int b) {
if (a<b) {
return a, b;
} else {
return b, a;
}
}
void test() {
int age, String name = getNameAndAge();
printf("name=%s, name=%i", getNameAndAge());
int x, int y = sort(random(100), random(100));
printf("x=%i, y=%i", x, y);
x, y = y, x;
}
struct Celestial
{
String name;
int diameter;
List satellites;
}
Celestial newBody(String name, int diameter)
{
return newBody(nane, diameter, new List());
}
Celestial newBody(String name, int diameter, List satellites)
{
Celestial c = new Celestial()
c.name = name;
c.diameter = diameter;
c.satellites = satellites;
return c;
}
void test()
{
Celestial solarSystem = newBody("Sun", 696000,
new List().add(newBody("Mercury", 2439))
.add(newBody("Venus", 6051))
.add(newBody("Earth", 6371)));
}
Widget functions can be divided into several categories based on their functionality.
void startWidget(); void stopWidget();
When the WidSets mobile client is opened, the startWidget() function is called for all widgets installed on the client’s dashboard. In most cases, you should implement this function to create the widget’s minimized view to be displayed on the WidSets dashboard.
The stopWidget() function is called whenever a widget is reloaded or removed from the dashboard or when the WidSets client is terminated. You should implement this function to release system resources (if any) before the client is terminated.
Shell openWidget(); void closeWidget();
The openWidget() function is called when the user selects a widget from dashboard. This is when the widget is also opened to the maximized mode. Most widgets implement the maximized mode. Within this function a Shell for using the views is typically created. The views can be either defined in the widget.xml file or created dynamically.
The closeWidget() function is launched when the maximized mode is exited by either with popShell() or slideOut(), the last widget-created shell, or when the widget is stopped for any reason. Here you might usually want to, for example, cancel a timer or set it to "tick" less frequently.
MenuItem getSoftKey(Shell shell, Component focused, int key); Menu getMenu(Shell shell, Component focused);
When the user presses a softkey of a mobile device (normally a softkey is associated to the widget's menu), WidSets will call the getSoftkey()to inform the widget which softkey was just clicked. You must implement this function to detect the softkey and tell WidSets what to do with the event. The getMenu() function is called when a softkey is designed to associate with an open menu.
void actionPerformed(Shell shell, Component source, int action); boolean keyAction(Component source, int op, int code);
The actionPerformed() function is called when a key-pressed action on a softkey is detected, and the keyAction() function is called when the user clicks on an alphanumeric key (including the navigation key). These functions can be implemented to detect any actions done by the user and to process them accordingly. Remember that both actionPerformed() and keyAction() are system callback functions, and they should never be called directly.
Flow createView(String name, Object context) Component createElement(String viewId, String elementId, Style style, Object context);
The createView() function is used for creating a view for the widget. A view can be a minimized view or a maximized view depending on the widget's status.
Widget's UI components can be constructed within the createElement() function. This is a callback function and it gets called as a result every time the createView() function is called.
void timerEvent(Timer timer);
You can set up timers that notify your widget after a specified time or continuously. Timers are created using schedule(...) functions. These timers will then call the timerEvent(i.e. Timer timer) function of your script, or a separate TimerCallback function, if defined.
To release the timer resource, you need to call the cancel() function for any Timer objects created. This should be done when the timer is not needed anymore, or when a widget is terminated via the stopWidget() function.
void onSuccess(Object state, Value returnValue); void onFailure(Object state, String errorMessage);
Server-side services can be invoked by using the call(Object state, String service, Value argument) function. Responses from a server (as the result of the call() function) are dispatched via onSuccess() or onFailure() callback function indicating that the server call was successful or failed, respectively.
In case of multiple server-side service calls, the state parameter in these callback functions can be used to identify which call the response belongs to.
If you are familiar with Java programming language or any other programming language, working with the WidSets Scripting Language is not a difficult task at all. Consider how to implement a simple function which calculates and return the sum of two numbers in WSL:
int calculateSum(int number1, int number2) {
return (number1 + number2);
}
Inner functions are useful when implementing callbacks (like anonymous classes in java).
Typical example is calling server-side service and provide success- and failure-callbacks.
void getPhoneNumber(String name)
{
Value arg = [
"url" => "http://www.foo.com/phone",
"params" => ["name" => name]
];
call(null, "myService", "get", arg, ok, nok);
void ok(Object state, Value ret)
{
setBubble(null, name+"'s number is "+String(ret));
}
void nok(Object state, String error)
{
setBubble(null, "Could not find number for "+name);
}
}
This section describes the fundamental rules of WidSets Scripting Language.
All script functions and variables MUST be implemented within the ONLY class of a widget:
class
{
int globalVar = 100;
void firstFunction()
{
int localVar = 0;
}
}
However, there can be inner functions which can make things easy to do while keeping code elegant:
Flow createAddressView(String name, String addr, String city)
{
Flow flow = new Flow(getStyle("address.view"));
add("Name", name);
add("Address", addr);
add("City", city);
void add(String name, String value)
{
String text = format(“%s: %s”, name, value);
Label label = new Label(“address.field”), text);
label.setPreferredWidth(-100);
label.setFlags(VISIBLE|LINEFEED);
flow.add(label);
}
return flow;
}
Inner functions can access variables defined in the enclosing function and also invoke other inner functions. Unlike in Java, you don't have to mark variables as final in order to access them from inner functions.
All variables must be initialized and they exist within the scope where they are declared.
void firstFunction()
{
int j; /* error, missing assigment */
{
int c = 0;
}
{
int d = c; /* error, ’c’ is not visible here */
}
}
Explicit typecasting
boolean flag = false;
Text displayText;
void someFunction()
{
int zeroOrOne = int(flag); /* casting boolean to int type */
...
String str = String(zeroOrOne); /* casting int to string type */
displayText.setText(str);
}