Meson User Manual
Overview
"Meson" is the name of a suite of connected technologies which allow interactive applications with both 2D and 3D elements to be
developed quickly, and with a very small execution footprint. Like "Java" the name denotes a language, an object model of predefined
classes, and a runtime execution environment.
The ordinary deployment method of a Meson application is in an applet on a web page. The following example shows a typical use case:
<html><body>
<applet code='com.kaon.meson.MesonApplet' archive='mesonApplet.jar,rasterGluon.jar,sceneGluon.jar' width=400 height=300>
<param name='meson' value='
Applet.Primary.fill="336699";
Applet.Primary.image="/images/productDemo/splash.jpg";
Meson.gluon("com.kaon.meson.raster.RasterGluon");
Data.Primary.url="/apps/productDemo/program.jar";
'>
</applet>
</body></html>
|
In this example, a short program is given right in the HTML file, using the meson applet parameter. This program uses the
trick of giving an attribute value over multiple lines, in order to improve readability. Note, however, that the HTML processor strips out
the line feeds before passing the parameter to the applet, so the applet receives this program as one very long line. Therefore, each
line ends with a ; to break the statements up for the parser. This program sets the background color of the applet (used
until an image appears), then sets the initial image in the applet using a URL relative to this page. Next it loads the Java code used
for 2D (raster) operations, and then creates a data source to fetch the application program. This program would display its own progress
meter, and load other Java code to extend the functionality into the 3D space.
Note that there is no way to express the ' (apostrophe) character in a HTML parameter value. Therefore, this character is not
required in the Meson language. If you need to include ' in a program on a web page, the unicode version \u0027 can be used.
Developing a Meson program using only a browser to debug can be difficult. For this reason, Meson includes a console application
called "blackboard" which executes program files, and has a command-line interface into which expressions can be typed. In this way, it
is similar to a LISP development environment, where debugging and programming are performed with the same tool. In the context of the
blackboard application, the above program would be this:
Meson.newApplet(["Primary",400,300])
Applet.Primary.fill="336699"
Applet.Primary.image="/images/productDemo/splash.jpg"
Meson.gluon("com.kaon.meson.raster.RasterGluon")
Data.Primary.url="/apps/productDemo/program.jar"
|
To run the blackboard application with a command line interface, open a command window, and cd to the folder where Live 3D is installed. Then type the following: jre/bin/java -mx96M -jar blackboard.jar optionally followed by the names of text
files containing Meson program statements. To run the blackboard program non-interactively, just drag a program text file onto the
Blackboard.exe launcher icon.
The blackboard application adds a few items to the Meson environment:
-
Meson.newApplet takes an array with up to 5 elements as its argument. First is the name of the applet, which can be prepended with a
* to request an applet window with no title bar or close button. Then width and height, followed optionally by left and top screen coordinates.
-
Meson.exit takes a single number argument, causing the blackboard application to terminate with that exit code.
- The attribute javaWindow is added to the Applet object, which can then be manipulated using Java reflection.
- The attribute windowClosed is added to the Applet object, with the default value {Meson.exit(0)}. This can be changed by the application, as needed.
Conceptual Framework
The heart of a Meson environment is the blackboard. This is a common place where all data is stored. Each piece of data on the
blackboard (each "attribute") has a name and a value. For example, Meson.clock ::= 5.3 is a way of expressing that the datum
called "Meson.clock" has the value "5.3". The power in the Meson language comes from the ability to put expressions into the blackboard,
which get their values by performing operations on other attributes in the blackboard. For example, Image.Blue.x ::= Image.Yellow.mouseX+50
says that the value of the attribute Image.Blue.x should always be 50 larger than the current value of the attribute
Image.Yellow.mouseX. These two examples are expressed in the Meson language as follows:
Meson.clock=5.3
Image.Blue.x={Image.Yellow.mouseX+50}
|
The Meson.clock example is called an immediate expression, whereas the Image.Blue.x example is
a deferred expression. When an expression references an attribute on the blackboard which is defined by a deferred
expression, that expression is evaluated. In the semantics of Java, a deferred expression is like a method, whereas an immediate
expression is like an instance variable. For almost all cases, deferred expression can fully describe the dynamic state of the sytem.
However, for the few cases where this is not true, the Meson runtime provides the concept of a Trigger. A trigger combines
some sort of test, with an expression to evaluate under conditions described by the test. There are several variations of Trigger, to
detect "transition to true" conditions, "value changed" conditions, and "value might have changed" conditions. Triggers are only
evaluated when the attributes in their test are assigned new values. In the case of deferred expression, the Trigger wll be tested when
any attribute used in that expression is assigned a new value. In general, there are two ways to express most relationships between
attributes:
ChangeTrigger.ToolCenter.test={Display.Primary.width}
ChangeTrigger.ToolCenter.exec={Image.Toolbar.x=Display.Primary/2}
|
Image.Toolbar.x={Display.Primary.width/2}
|
When a choice like this exists, do not use the Trigger. The latter expression is more concise, easier to debug, and more
efficient than the former expression. The temptation will probably be to use the former method, because that is how it would be done in a procedural language
like Java or Basic. But Meson is a declarative language, not a procedural one. A Trigger should be used only when there is no way to express the
relationship in a declarative manner, as shown in the following example:
Area.Button1.state={Area.Button1.press?"press":"off"}
Trigger.Button1.test={Area.Button1.press}
Trigger.Button1.exec={counter=counter+1}
|
The blackboard uses a smart cache to minimize the runtime cost of using deferred expressions. For example, if Image.Toolbar.x is defined as follows:
Image.Toolbar.x={Display.Primary.width/2}
|
the first time anything reads Image.Toolbar.x from the blackboard, the calculation will be performed. This value is cached,
and every other blackboard value which contributed to its calculation (just Display.Primary.width in this case), is tagged
with the cache dependency. If Display.Primary.width changes, then the cached value of Image.Toolbar.x will be
dropped. But until then, subsequent reads of this attribute will be essentially free. In a typical Meson application, about 90% of
attribute fetches from the blackboard hit the cache.
The presence of the cache is generally transparent to the Meson programmer. However, there is one case which requires special care:
programming by side effect. When an attribute on the blackboard is really being used as a procedure, callers must use care
to reference it using procedure call semantics. For example:
increment={counter=counter+1}
Trigger.Button1.test={Area.Button1.press}
Trigger.Button1.exec={increment()}
|
Note the use of parenthesis in the read of increment. This tells the cache system to evaluate the expression, regardless
of whether a value might be cached.
The blackboard is augmented with a scratch data storage area, called the notebook. The notebook has pages, which can
store attributes, much like the blackboard. The idea of the notebook is that it is a semi-private area where an expression can take notes without polluting the
blackboard. For example:
distSquared={#dx=Applet.Primary.mouseX-cx;#dy=Applet.Primary.mouseY-cy;
#dx*#dx+#dy*#dy}
|
In this example, two notebook attributes (#dx and #dy) are used to store temporary values. Reading and writing
attributes in the notebook is more efficient than working on attributes on the blackboard, because notebook attributes have two
restrictions: notebook attributes cannot be tested in a Trigger, and notebook attributes cannot be objects (for example, #Image.Foo.x does
not create an object of class Image, whereas Image.Foo.x would implicitly create such an object). Also, notebook
attributes are not cached.
An application uses attributes on the current page of the notebook with the # operator. It is also possible to
use attributes on the next page of the notebook, using the ^ operator. This facility is provided as an argument passing
mechanism -- when an attribute is
referenced using function notation (for example, Meson.sin(3.14)), the notebook page is advanced. This way each function
can safely write any attribute without concern for trashing someone else's notes.
squareSum={#dx*#dx + #dy*#dy}
distSquared={squareSum(^dx=Applet.Primary.mouseX-cx;
^dy=Applet.Primary.mouseY-cy)}
|
The remainder of this document fully describes the Meson language and object model.
Syntax
Meson programs are written in a line-oriented declarative language. A typical line of a Meson program looks like this:
Attributes can be simple names, or they can be fully qualified object members. For example:
Each delcaration occurs on a single logical line. If the text is long, lines can be split by ending them with \ (similar to some
BASIC interpreters). Unbalanced curly braces implicitly cause line continuation:
Image.Label.text="This is a very long string "+ \
"which has been split across lines."
Scene.3d.width={Display.Primary.Width-
Image.RightToolbar.Width}
|
Literal symbols include quoted strings (as with Javascript, the forms "string" and 'string' are both
allowed, to ease embedding quote and apostrophe characters within strings), the special strings true
and false, and any string of non-operator characters starting with any of the
following: ._-0123456789 (period, underscore, minus sign, and digits). In essence, the quotes are optional when symbols
start with these characters. Whether a symbol denotes a number depends on how it is used, not on what its starting character is.
The symbols true and false are recognized by the parser and need not be quoted.
Using quotes around a string allows the use of any special character, and also enables the use of escaping (\n for newline,
\t for tab, \" for a quote, \' for an apostrophe, and \uXXXX for a unicode
character). Note that the parser reads the text as UTF-8 encoded unicode, so using unicode escapes is only necessary if the text is
being edited with a ASCII editor, like Notepad.
Style.Default.color=336699
Style.Default.color="336699"
Style.Default.color="FFFFFF"
black="ff000000"
text='He said, "Hello".'
text="It's my party..."
Style.Default.color=black
Style.Default.color=@("black")
Image.Logo.text="Powered By\nwww.strata.com"
Image.Temp.text={"Current Temp: " ~ temp ~ "\u00B0 C"}
|
There are two kinds of expressions which can be used on the right side of an assignment: immediate and
deferred. An immediate expression is evaluated right away, whereas a deferred expression is like
a little program which will run on demand:
|
Examples of immediate expressions.
Scene.3d.width=300
Image.Toolbar.anchor=_C
Image.Toolbar.x=Scene.3d.width/2
Examples of deferred expressions.
Scene.3d.width={Display.Primary.width}
Image.Toolbar.x={Display.Primary.width/2}
|
Expressions can combine terms using a variety of operators:
-
* / % Multiply, Divide, Remainder
-
+ - Add, Subtract
-
! & | Not, And, Or (boolean operators)
-
∪ ∖ Union, Set Minus (array operators; ++ -- also accepted)
-
~ Concatenate (string operator)
-
≈ < > Equal to, Less Than, Greater Than (== is accepted in place of ≈)
-
≠ ≤ ≥ Not Equal to, Less or Equal, Greater or Equal (!= <= >= also accepted)
-
? : Test (a?b:c means if (a==true) then b else c), the : clause is optional
-
@ # ^ Attribute Reference, Local Reference, Parameter Reference
-
¬ Dereference (-> also accepted)
-
= Assignment
-
; , Statement Separators
-
{ } Deferred Expression
-
( ) Grouping/Function Operator
-
[ ] Array Operator
-
« » Prefix Section (<< and >> also accepted)
The following examples demonstrate some syntactic paradigms:
Area.Measure.state={Scene.3d.mode=="rotate"?"on":"off"}
attr={#dx=(Image.Pop.x-Image.base.x); #dx * #dx}
square={square.arg * square.arg}
attr=(square.arg=(Image.Pop.x-Image.base.x); square())
square={#arg * #arg}
attr=square(Image.Pop.x-Image.base.x)
squareSum={#x*#x + #y*#y}
attr=squareSum(^x=Image.Pop.x-Image.base.x;^y=Image.Pop.y-Image.base.y)
power={#exp==1?#base:(#base*power(^base=#base;^exp=#exp-1))}
Image.Expr.text="5^6=" ~ power(^base=5;^exp=6)
power={#exp==1?#base:(#exp=#exp-1;#base*power)}
theImage="Image.Main"
theX={@(theImage~.x)}
theY={theImage->y}
hello={Meson.log("Hello")}
helloWorld=hello+{Meson.log("World")}
Foo.Class<<
.bar=1 /* equivalent to Foo.Class.bar=1 */
.baz=2 /* equivalent to Foo.Class.baz=2 */
>>
|
Built-in Functions
The Meson interpreter defines a handful of built-in functions:
foreach(string elem, array in, deferred do) iterates over the elements in an array:
numbers=[one,two,three]
count={^c=0;foreach(^elem="i";^in=numbers;^do={#c=#c+1;@Meson.log(#c~" = "~#i)})}
|
try(deferred exec, deferred catch) returns the value of the exec clause unless an exception is thrown, in which case the value of the catch clause is returned. When the catch clause is evaluated three additional local attributes are placed in the notebook: exception fully qualified Java class of the exception; message message member of the Java exception; javaException actual Java Exception object.
width="90%"
widthNum={try(^exec={width+0};^catch={
Meson.log("E: {"~#exception~"}");
Meson.log("M: {"~#message~"}");
Meson.log("J: {"~#javaException~"}");
-1})}
|
Meson.length(array arg) returns the number of elements in the array.
Meson.assert(boolean arg) throws an exception if the passed arg is not equal to "true":
a=5
b={Meson.assert(a==5); a}
c={b*b}
d={a=3}
e=d+c
|
Meson.throw(string arg) throws an exception
Meson.log(string arg) prints a string to the console
Meson.dump(string arg) dumps the blackboard contents to the console. Only blackboard items starting with the passed argument are dumped.
Use Meson.dump("") for a full dump.
Meson.getMethod(string class, string method, array args) and Meson.callMethod(java.lang.reflect.Method method, array args) are used together to access Java methods:
randMethod=Meson.getMethod(^class="java.lang.Math";^method="random";^args=[])
rand={Meson.callMethod(^method=randMethod;^args=[])}
Image.Foo.x={rand * Display.Primary.width}
Meson.atan2Method=Meson.getMethod(^class="java.lang.Math"; \
^method="atan2";^args=["double","double"])
Meson.atan2={Meson.callMethod(^method=Meson.atan2Method;^args=#arg)}
someAttr=Meson.atan2([1, 0.5])
|
Note that for non-static methods, the Java object to operate on should be passed as the first array element to
Meson.callMethod but should not be declared in the array passed to Meson.getMethod.
Use the built-in attribute null to pass a null pointer as an argument.
Meson.newInstance(string className) creates an instance of a Java class using the no-arguments constructor.
Meson.gluon(string arg) loads a Gluon to add more built-in functions:
Applet.Primary.image="splash.jpg"
Meson.gluon("com.kaon.meson.raster.RasterGluon")
Display.Primary.file="splash2.jpg"
|
Each bit of functionality in the Meson system is provided by a Gluon. A Gluon is a set of Java classes which extend the
native capabilities of the Meson language. This document describes functions provided by the Raster and Scene Gluons.
Meson.showDocument(string applet, string url, string target) is used to request than an applet show an HTML
page (url parameter) in a frame or window (target parameter).
Meson.showStatus(string applet, string status) is used to request than an applet show a message in the the
status bar of the browser window.
Meson.jsEval(string javascript) is used to invoke an arbitrary javascript expression in the context of the web page that
includes the applet. Note that the MAYSCRIPT attribute must be added to the applet tag on the HTML page if this method
is used.
Meson.addContextMenu(string applet, string label) adds a label to the applet context menu. Calling this
with the ^label="-" inserts a separator. When the user accesses an item on the context menu, this label value is placed
in the applet's menuItem attribute.
Meson.addContextMenu(^applet="Applet.Primary", ^label="CNN")
Trigger.CNN.test={Applet.Primary.menuItem=="CNN"}
Trigger.CNN.exec={Meson.showDocument(^applet="Applet.Primary", ^url="http://cnn.com", target="_blank")}
|
Meson.unique generates a unique identifier, useful for creating helper objects.
setInterval={#t="Timer."~Meson.unique();#t->delay=#delay;#t->repeat=true;#t->exec=#exec;
@(#t->start);#t}
|
Meson.checkpoint captures the entire state of the blackboard into an attribute
Meson.restore(arg) restores the state of the blackboard to the passed checkpoint
Meson.addContextMenu(^applet="Applet.Primary", ^label="Checkpoint")
Meson.addContextMenu(^applet="Applet.Primary", ^label="Restore")
ckpt=Meson.checkpoint()
Trigger.Checkpoint.test={Applet.Primary.menuItem=="Checkpoint"}
Trigger.Checkpoint.exec={ckpt=Meson.checkpoint()}
Trigger.Restore.test={Applet.Primary.menuItem=="Restore"}
Trigger.Restore.exec={ckpt=Meson.restore()}
|
Note that the checkpoint itself is not in the checkpointed blackboard, so restore returns the checkpoint, so that it can
be stored into the restored blackboard. If the Restore trigger simply said Trigger.Restore.exec={Meson.restore()} then
the attribute ckpt would disappear after restore, since it is restoring a blackboard which had no ckpt
attribute on it.
Meson.setInterval(number delay, deferred exec) creates a repeating timer, similar to the JavaScript setInterval function
Meson.setCurrentDataSource(string arg) sets the default data source for images created between now and the next time
this is called. This is used by the Data class of the Raster gluon to control defaulting when reading a meson program, and the data used by that program,
from the same file. The argument should either be the name of a Data object (Meson.setCurrentDataSource(Data.myProg)) or
a URL relative to the current document base (Meson.setCurrentDataSource("http:/data/")). Since this is set automatically
by the Data object, it is unlikely an application will ever need to call this function.
Meson.clock holds the time since Meson initialization, in seconds.
Meson.frameStep holds the amount of time since the last tick, in seconds.
Meson.documentBase holds the URL of the applets using this blackboard.
Meson.displayDepth holds the bit depth (16 or 32) of the display on which the applet appears.
Meson.notebookPages holds the number of pages in the notebook (32, by default). An application can increase this limit
if it needs to use recursive evaluations which are very deep.
clear black green silver lime gray olive white yellow maroon navy red blue purple teal fuchsia aqua are all predefined
with their CSS-equivalent color values (clear has alpha channel of 0x00, all other have alpha of 0xff)
Meson.isMac is true on Mac OS (9 or X) platforms
Meson.language holds the two-letter code of the default user language as reported by the O/S (en, es, zh, etc...)
Object Models
Several classes are included in the the baseline Meson system: Trigger, ChangeTrigger,
HairTrigger, Timer, Ticker, Applet, and GenericPeer.
Applications create instances of these classes with the notation
Class Name.Instance Name.attributes...=value.
In other words, an instance of a class is created when one of the attributes of that instance is referenced.
Each class defines a set of attributes which have special meaning in instances of that class. The application may use custom
attributes within the scope of an instance as well. The predefined attributes have types which the system expects to find when it parses
them. These are:
-
string a string of unicode characters
-
integer a positive, negative, or 0 whole number
-
number an integer or floating point number (when this represents an integral values, such as pixels, floating point
values will be rounded to the nearest integer)
-
color an ARGB color value specified as 4 or 8 hex digits, or an RGB color value specified as 3 or 6 hex digits
(note that the character # used in HTML colors must be omitted, because # has special meaning)
-
enum a value from the specified list of choices
-
boolean true or false
-
array a set of values (generally, if a value of a different type is used where an array is expected, a one-element
array will be created automatically)
-
attribute the name of an attribute or class instance
-
native a native Java object
-
deferred a deferred expression
Assignments which do not start with a class name create attributes in a global variable space. Assignments which start with a #
create attributes on the current notebook page. Assignments which start with a ^ create attributes on the next notebook
page, which will be the current notebook page of the next function invoked.
The defaults for a class can be overridden using the special object Class which acts as a template during
instantiation. For example, to change the default for Images to use 16-bit color depth instead of 32-bit color depth, use
Image.Class.depth=16. Note that this will not retroactively change existing instances. To implement retroactive changes
to defaults, use deferred assignments: defaultImageDepth=32 and
Image.Class.depth={defaultImageDepth}. In this example, images get {defaultImageDepth} as their depth
attribute, so that a subsequent assignment defaultImageDepth=16 would flow through to the images.
Applications can create custom classes using the special member extends. For example,
HotImage.extends="Image" creates a new class HotImage which extends Image. The application can
then assign attributes to HotImage.Class which will become the defaults for HotImage objects. Note that if an
attribute matches the name of an attribute in the superclass, then the subclass initializer sets the superclass attribute instead. For
example, if HotImage.Class.layer=5, then when the object HotImage.Foo is created, the assignment
Image.Foo.layer=5 will occur. In this example, HotImage.Foo.layer
becomes a proxy to the underying attribute Image.Foo.layer, so reads and writes of either attribute actually change the one
in the base class.
A class can extend multiple base classes. For example, Display.extends=["Applet","Image"]. The order in which base classes
are listed is used to resolve conflicts. For example, both Applet and Image define the width
attribute. Since Display extends Applet first, the default value of width comes from
Applet, and the Display and Image versions of the object both proxy width from Applet:
A.extends=""
A.Class.a=1
A.Class.x=2
B.extends=""
B.Class.b=3
B.Class.x=4
C.extends=["A","B"]
C.Class.c=5
C.Class.a=6
Meson.assert(C.foo.b==3)
Meson.assert(C.foo.x==2)
Meson.assert(C.foo.a==6)
Meson.assert(C.foo.x=9;(A.foo.x==9 & B.foo.x==9 & C.foo.x==9))
|
The $ character is substituted dynamically in class initialization with the name of the object being created. For example,
HotImage.Class.x={HotSpot.$.x} implies that the object HotImage.Reset automatically get the attribute assignment
HotImage.Reset.x={HotSpot.Reset.x}, allowing automatic linking between objects in the user-defined class HotImage and similarly
named hotspots. Similarly, $$ substitutes the fully qualified name including the class and instance parts.
i18n.OK="Way!"
i18n.Cancel="No Way!"
I18NImage.extends="Image"
I18NImage.Class.text={i18n.$}
buttonPadding=5
I18NImage.OK.anchor=SE
I18NImage.OK.x={Image.Dialog.width/2 - buttonPadding}
I18NImage.OK.y={Image.Dialog.height - buttonPadding}
I18NImage.Cancel.anchor=SW
I18NImage.Cancel.x={Image.Dialog.width/2 + buttonPadding}
I18NImage.Cancel.y={Image.Dialog.height - buttonPadding}
|
A class can be given a special member new which is an expression evaluated when an instance is created, just after all
the predefined Class attributes are set. This facility can be used to automatically create partner attributes or objects
which go along with instances of a class.
TipImage.extends="I18NImage"
TipImage.Class.time=2
TipImage.new={ Timer.Hide$.delay=$$.time;
Timer.Hide$.exec={$$.layer=-1};
Trigger.Hide$.test={$$.layer>-1};
Trigger.Hide$.exec={Timer.Hide$.start()} }
TipImage.Class.anchor=_S
TipImage.Reset.x=Area.Reset.x+Area.Reset.width/2
TipImage.Reset.y=Area.Reset.y
SlowTipImage.extends="TipImage"
SlowTipImage.Class.time=5
SlowTipImage.Foo.time=1
|
The prior example demonstrates the order in which initialization of objects takes place when subclassing is being used:
- superclass (recursively) members
- subclass members
- superclass (recursively) new
- subclass new
- instance members
In the example, the final assignment results in the following assignments (in this order) at run time:
Image.Foo.text={i18n.Foo}
TipImage.Foo.time=2
Image.Foo.anchor=_S
TipImage.Foo.time=5
Timer.HideFoo.delay=TipImage.Foo.time
Timer.HideFoo.tick={Image.Foo.layer=-1}
Trigger.HideFoo.test={Image.Foo.layer>-1}
Trigger.HideFoo.exec={Timer.HideFoo.start()}
TipImage.Foo.time=1
|
The final assignment has no effect, because the assignment to Timer.Hide$.delay was an immediate expression. In order for
this example to have the intended results, a deferred expression should have been used:
TipImage.new={ Timer.Hide$.delay={TipImage.$.time};
|
Then the initialization would have been:
Timer.HideFoo.delay={TipImage.Foo.time}
|
which would respond to subsequent changes to the time member of TipImage objects.
The .new attribute is unique, in that each one in a class hierarchy has an opportunity to run during initialization.
Contrast this with other attributes, in which the proxy substitution rules described above cause subclass members to merely replace
superclass members at instantiation. Sometime it is desirable for the subclass to override an attribute (particularly one which holds
a deferred expression), but keep access to the superclass definition as well. This can be accomplished by accessing the
special Class instance member, and using the + operator to join deferred expressions together:
Foo.extends=""
Foo.Class.someMethod={Meson.log("$$ " ~ #arg)}
Bar.extends="Foo"
Bar.Class.access=0
Bar.Class.someMethod=Foo.Class.someMethod+{$$.access=$$.access+1}
|
Another case where + is used to join expressions is adding functionality to an already-defind method:
Foo.Class.new=Foo.Class.new+{Meson.log("Detected creation of object: $$")}
|
By convention, class and object names start with capital letters, while attributes start with lowercase letters. This language
is case sensitive.
Basic Object Model
Class:
Trigger
A trigger runs a deferred expression when the value of a test expression changes to true.
|
This example sets an attribute in response to a mouse press on the Area called Button
Trigger.Show.test={Area.Button.press}
Trigger.Show.exec={Image.PressedImage.layer=9}
|
|
This example sets an attribute in response to a mouse release on the Area called Button
Trigger.Hide.test={!Area.Button.press}
Trigger.Hide.exec={Image.PressedImage.layer=-1}
|
| An expression which should evaluate to true or false |
| Type | deferred |
| This expression is evaluated when the test transitions from false to true |
| Type | deferred |
Class:
ChangeTrigger (Extends Trigger)
A change trigger runs a deferred expression when the value of a test expression changes.
|
This example increments a counter whenever an area changes state in any way
ChangeTrigger.StateCount.test={Area.Button.state}
ChangeTrigger.StateCount.exec={Area.Button.stateCounter=Area.Button.stateCounter+1}
|
| An expression which is evaluated |
| Type | deferred |
| This expression is evaluated when the test value changes |
| Type | deferred |
Class:
HairTrigger (Extends Trigger)
A hair trigger runs a deferred expression when anything referenced in the test might have changed, regardless of whether the value
of the test expression actually changed. Note that writing a value to the blackboard which is identical to the value
already there will not fire a HairTrigger.
|
This example prints a message whenever the layer or alpha is modified
HairTrigger.DebugVis.test={Image.Foo.layer;Image.Foo.state}
HairTrigger.DebugVis.exec={Meson.dump(Image.Foo)}
|
| An expression |
| Type | deferred |
| This expression is evaluated whenever anything in the test might have changed |
| Type | deferred |
Class:
Timer
Timers are used to perform actions after a delay, or periodically.
|
This example displays a popup image for a hotspot when the mouse enters, and uses a timer to hide the hotspot 2.5 seconds after
the mouse exits.
Timer.HidePort.exec={Image.portPopup.layer=-1}
Timer.HidePort.delay=2.5
Trigger.SP1.test={HotSpot.Port.hover}
Trigger.SP1.exec={Image.portPopup.layer=9}
Trigger.SP2.test={!HotSpot.Port.hover}
Trigger.SP2.exec={Timer.hidePort.start()}
|
| The delay between events generated by this timer (seconds). |
| Type | number |
| Default | 0 |
| Controls whether the timer fires once, or periodically. |
| Type | boolean |
| Default | false |
| This expression is evaluated when when the timer ticks. |
| Type | deferred |
| Reading this attribute starts the timer. |
| Restrictions | Use function() semantics |
| Reading this attribute stops the timer without firing it. |
| Restrictions | Use function() semantics |
Class:
Ticker
Tickers are used to evaluate an expression every frame. An order member is present which can be used to control the order
of execution of Tickers in the system.
| Tickers execute in increasing order, starting at 0. The order of execution
for Tickers with the same order attribute is the order in which they were created. Setting the order to a value
less than 0, such as -1, will prevent the ticker from ticking. |
| Type | number |
| Default | 0 |
| This expression is evaluated when when the Ticker ticks. |
| Type | deferred |
Class:
Applet
Applet objects represent applets on web pages. Applet is the only graphical class included in the base object model, in order to
keep the initial footprint of Meson very small. Applications will typically use the Applet class only to display a splash logo. After
loading the Raster gluon, the application will then use the Display class which extends the Applet class with image manipulation
capabilities.
The name of an applet comes from it's mesonName property on the HTML page. If no name is given, the default Applet
name is Primary. If the application uses multiple applets on the same Blackboard, names must be assigned
explicitly.
| This holds the java.applet.Applet object for the
applet. |
| Type | native |
| Default | "" |
| Restrictions | Read Only |
| This holds the java.awt.Image object used as the
background of the applet. Initially, this is based on the image attribute, but when the Raster gluon is loaded, the
Display class replaces it with a new image to reflect the dynamic state of the executing program. |
| Type | native |
| Default | "" |
| Restrictions | Read Only |
| The fill is used at Applet startup to control the background color. |
| Type | color |
| Default | fff |
| The image attribute is a URL (relative to the document on which the applet is
placed) of an image to show in the Applet while the remainder of the program is loading. Progressive JPG or Interlaced GIF images
can be used to get immediate content onto the screen. |
| Type | string |
| Default | "" |
| When set to true, the applet will ask Java to initiate a
repaint. |
| Type | boolean |
| Default | false |
| Width of the applet. This may change if the applet is in
a resizable window, and uses percentage for its width attribute. |
| Type | integer |
| Default | 0 |
| Restrictions | Read Only |
| Height of the applet. This may change if the applet is in
a resizable window, and uses percentage for its height attribute. |
| Type | integer |
| Default | 0 |
| Restrictions | Read Only |
Keyboard and mouse input is delivered into Applet attributes. In order to ensure Trigger objects fire correctly, the
events are queued as they happen, so that if multiple events happen during a frame, the next frame will get all those events in
order. For example, if the left mouse button is clicked, the press element will be set to true
(causing Triggers watching for press to execute), and then to false (causing release Triggers to execute).
| The X position of the mouse, measured from the left side
of the applet. Note that browsers typically only deliver mouse coordinates when the applet has focus. |
| Type | integer |
| Default | -1 |
| Restrictions | Read Only |
| The Y position of the mouse, measured from the top
of the applet. Note that browsers typically only deliver mouse coordinates when the applet has focus. |
| Type | integer |
| Default | -1 |
| Restrictions | Read Only |
| True when the left mouse button is being pressed
in the applet. |
| Type | boolean |
| Default | false |
| Restrictions | Read Only |
| True when the Shift key is pressed and the applet has
focus. |
| Type | boolean |
| Default | false |
| Restrictions | Read Only |
| True when the Control key is pressed and the applet has
focus. |
| Type | boolean |
| Default | false |
| Restrictions | Read Only |
| Holds the most recently typed key. Triggers which respond to keystrokes can set
this back to "" after firing, to respond to mulitple presses in a row. For special keys, this holds the key
name (Enter, Left, Right, Up, Down, Tab,
Delete, Back). For all other keys, it holds the unicode letter. |
| Type | string |
| Default | "" |
Class:
GenericPeer
Generic Peer is extended by other objects which bear a very close relationship to objects implemented by Gluons in Java code.
Their primary purpose is to provide a simple, consistent way for Meson programs to invoke methods on these native objects. Their use
is entirely optional, as they merely wrap calls to built-in functions like Meson.getMethod and
Meson.callMethod.
| Specifies the fully-qualified Java class name of the native peer class. |
| Type | string |
| Holds the native object which is created in reponse to this object being referenced in the
Meson program. Note that a no-arguments constructor is used by default, so a native class using this facility should use separate
initializers (similar to the design pattern used in Applets and Servlets). |
| Type | native |
| Invokes a method on the native object. Arguments are as follows:
-
method: native method name as a string
-
types: array of argument types. For primitive types, use strings like float or long. For object
types use the fully-qualified class name, such as java.lang.String. For array types, use the Java method signature conventions (for
example, "[[F" for a two-dimensional array of float, or "[Ljava.lang.String;" for a
one-dimensional array of strings.
-
args: array of arguments, which must correspond to the values passed in the types parameter. As
explained above, use null for null parameters.
|
| Type | deferred |
| Looks up a method of the native object. When a method is going to be called very
frequently, it is a good idea to look it up once in advance and cache it, rather than looking it up over and over
with callMethod. Arguments are as follows:
-
method: native method name as a string
-
types: array of argument types. For primitive types, use strings like float or long. For object
types use the fully-qualified class name, such as java.lang.String. For array types, use the Java method signature conventions (for
example, "[[F" for a two-dimensional array of float, or "[Ljava.lang.String;" for a
one-dimensional array of strings.
|
| Type | deferred |
Raster Gluon
The Raster gluon adds several classes to Meson: Anim, Data, Image,
Display, Area, and Style. It also adds several built-in functions.
Raster Built-in Functions
Meson.sin(number arg),
Meson.cos(number arg),
Meson.tan(number arg),
Meson.atan(number arg),
Meson.atan2(array arg),
Meson.round(number arg),
Meson.ceil(number arg),
Meson.floor(number arg),
Meson.ln(number arg) (natural log),
Meson.exp(number arg) (natural exponent)
provide access to
the equivalent methods in java.lang.Math. For convenience, the attributes Meson.degToRad and Meson.radToDeg
are also defined.
Ticker.Dot.exec={currentAngle=currentAngle+Meson.frameStep*rateDegPerSec}
rateDegPerSec=360/60
Image.Dot.x={dotRadius * Meson.cos(currentAngle*Meson.degToRad)}
Image.Dot.y={dotRadius * Meson.sin(currentAngle*Meson.degToRad)}
dotRadius={(Image.Dot.parent~.width)/2-Image.Dot.width}
|
Meson.formatFloat(number value, string format) returns the number formatted according to the user's regional numeric
formatting conventions, as specified by the OS. The format specifier is of the
form integerDigits[.decimalDigits]. That is, the if no decimal part is given, the value will be shown as an
integer.
Raster Object Model
Class:
Anim
Animation objects are used to set attributes to values over time. The animation uses a combination of linear interpolation and
exponential smoothing, to allow values to change in a variety of ways.
|
This example shows how to use an Anim object to make a toolbar slide in when the mouse enters the area (like a desktop taskbar with
auto-hide).
Area.ShowToolbar.image="Image.Toolbar"
Anim.ToolY.attr=["Image.Toolbar.y"]
Anim.ToolY.rate=10
Anim.ToolY.highPriority=true
Anim.ToolY.goal=[{Display.Primary.height-(Area.ShowToolbar.hover?Image.Toolbar.height:5)}]
|
| The attributes which are controlled by this animation. |
| Type | array of attribute |
| The value to be assigned to each attr over time. |
| Type | array of number |
| The maximum rate (per second) at which to change the value. If this value is <0,
the rate is not limited. |
| Type | number |
| Default | -1 |
| The exponential smoothing constant to apply when changing the value. A value of 0
changes instantly, whereas a value of 1 will never change. This parameter controls the amount of goal value to blend with the current
value each time step, based on the equation weight=smoothtimeStepSeconds. Typical values are around 0.05. |
| Type | number |
| Default | 0 |
| When an attribute value is this close to the goal
(|goal-attribute|≤threshold) the attribute will be set to exactly the goal. |
| Type | number |
| Default | 0.001 |
| The animation only operates when this attribute
is true. |
| Type | boolean |
| Default | true |
| If this is set to true, the animation will set its
own enabled attribute to false when the attribute value reaches the goal. This is used for "one shot"
animations. |
| Type | boolean |
| Default | false |
| If modulus is non-zero, then the attribute will skip up or down an appropriate amount
to never be more than half the modulus away from the goal. For example, when the attribute is an angular measure, a modulus
of 360 will lead to the attribute following the shortest path around the circle to the goal. |
| Type | number |
| Default | 0 |
| A high-priority animation sets an internal flag in the applet context
when it is running (i.e., when the attribute value is not the goal, and the animation is enabled). This flag is consulted by various
low-priority tasks, such as 3D Scene anti-aliasing, to control sharing of CPU cycles. In a nutshell, a high-priority animation will
be visually smoother than a normal priority one on a heavily loaded system. For animations with moving rasters, such as the toolbar animation in the
above example, this will give a better appearance. For animations of alpha parameters, it is generally not necessary, as the user
cannot see the subtle frame rate differences involved. |
| Type | boolean |
| Default | false |
Class:
Data
Data objects represent a bundle of resources used by a Meson application. The data file referenced by this object is in the ZIP (JAR)
format, and may contain an arbitrary mix of .txt files containing Meson programs, .jpg and .gif files used by those programs, 3D scene
data including wavelet .kwl files and compressed binary data, and other ZIPs or JARs. The best compression is achieved by building a compressed JAR containing a single uncompressed JAR with
the files. The resulting compression is much better than a simple compressed JAR.
| URL (relative to the page the applet is on) of the JAR file containing the data |
| Type | string |
| State of the data file. Data starts
in the _NEW state, immediate transitions to the _OPEN state where data is read, and transitions to the
_CLOSED state when reading is complete. It may transition to the _FAILED state if any error
occurs. |
| Type | enum
_NEW, _OPEN, _CLOSED, _FAILED |
| Restrictions | Read Only |
| When the state is _FAILED, this holds
the error message |
| Type | string |
| Restrictions | Read Only |
| Contains the content length, as reported by the server. Note
that this may be -1 if the server does not know the content length. |
| Type | number |
| Restrictions | Read Only |
| Contains a count of bytes read so far. |
| Type | number |
| Restrictions | Read Only |
| Set this to true to temporarily stall reading the
data. |
| Type | boolean |
| Default | false |
| Contains the list of files read from this data source so far. |
| Type | array |
| If the data source contains wavelet-encoded images, this holds the
percentage of image data which has been decoded so far. |
| Type | number |
| Default | 100 |
| When set to true, the file read will stop, and the state will transition back
to _NEW. This will cause the file to immediately start loading again, unless you first set the url attribute to "". |
| Type | boolean |
| Indicates that the URL points to Meson code or a ZIP/JAR archive which should be parsed. |
| Type | boolean |
| Default | true |
| When the parse attribute is false, the data pointed at by the URL will be read into a string and placed into this attribute. |
| Type | string |
Class:
Image
An image is a rectangular raster of pixels. There are three ways to create an image: from a file, by rendering text, or simply
allocating a blank area.
| Create the image from the specified file. The file may be a GIF or JPG format
image (PNG format is not supported in all browser environments, so it should be avoided). GIF files may use animation, although this
should be avoided where possible for performance reasons (using a multi-state image and flipping thru the states will yield faster
update rates). In cases where a continuous alpha channel
is required (in contrast to the On/Off alpha of GIF transparency), two images may be given, separated by an @ symbol.
The first file gives the color information, and the second gives alpha information. For example:
Image.Toolbar.file="toolbar.jpg@toolbarMask.gif".
The blue channel of the pixels in the GIF images are used as the alpha channel (in practice, a gray-scale GIF can be used,
since the red and green channels are ignored). The color pixels may come from either a JPG or GIF format file, however, if GIF is
used, it must not include transparency (specify transparency in the alpha channel file instead). Animation is not permitted in an
alpha channel GIF. |
| Type | string |
| Example | "top.jpg" |
| Create the image by rendering the specified text. The background of the
text comes from the buffer attribute. If no buffer color is given, the text will be on a transparent background. |
| Type | string |
| Example | "Open Lid" |
| Specifies the default spacing, in pixels, for tab stops (used when rendering
text containing the \t character). |
| Type | number |
| Default | 50 |
| Specifies explicit tab stop locations, in pixels. Note that, as with word
processing programs, the default tab spacing is used to the right of the last explicit tab stop. |
| Type | array |
| Default | [] |
| Text can be auto-wrapped while being rendered, to ensure the resulting image
does not exceed a certain width. This attribute controls that process. Note that spaces, tabs, language-specific rules (such as Japanese, where breaks between glyphs are allowed except in a few cases), and style-changes can result
in breaks (the non-breaking-space unicode character \u00A0 can be used to insert a non-breaking space between words). If a single
piece of unbreakable text is longer than will fit in the wrapWidth, then text wrapping will not be performed on that text. In this
case, the width member could end up larger than wrapWidth, if set implicitly. If you assign a particular
value to width then text which extends beyond this will be clipped. |
| Type | number |
| Default | 0 |
| When using the wrapWidth attribute, this selects the language rules to use when determining how to break long lines at word boundaries. |
| Type | string |
| Default | {Meson.language} |
| When using the wrapWidth attribute, this selects the country-specific language rules to use when determining how to break long lines at word boundaries. |
| Type | string |
| Default | "" |
| Create a buffer with the specified fill color |
| Type | color |
| Example | "FF336699" |
| Used together with a buffer, this softens the alpha channel all the
way around the rectangular image by the specified number of pixels on each side. |
| Type | number |
| Default | 0 |
Images can represented internally using 32-bit ARGB, or 16-bit YCrCb representation. In the 32-bit setting, alpha and the 3 color
channels are represented by 8 bits each. In the 16-bit setting, each adjacent pair of pixels share a chominance value, and each has
its own luminance. Both modes support a full 256 gray levels, but only the 32 bit mode supports alpha channels and the complete range
of colors. For textures compressed with JPEG compression, there is nothing to be gained using 32-bit representation, because JPEG
forces each pair of adjacent pixels to have the same chrominance.
| Set the color depth to be used to represent this image |
| Type | enum 16, 32 |
| Default | 32 |
Text images will always use font smoothing when the underlying Java implementation supports it. When it does not, font smoothing
can be emulated to varying degrees of precision. The higher the degree, the longer it takes to render the text initially. Once the
text is set, however, the speed of rendering is not impacted by smoothing.
| Font anti-aliasing control. A value of 0 does no
anti-aliasing, 1 does a little anti-aliasing, while value of 2 does maximum anti-aliasing. Note that text which changes frequently, such as the measuring distance,
should use a value of 0 for best performance. This only controls the default anti-aliasing for an image. Individual text Styles
can specify a different level of text anti-aliasing, which will take precedence over this setting. |
| Type | enum 0, 1, 2 |
| Default | 2 |
An image can have multiple states, which are stacked vertically, with the first state on top, the next one below it, and so on. The version of
an image which appears on the screen is the first state overlaid with other states as specified by Area objects within the
image.
| Names the states represented within the image. |
| Type | array |
| Default | ["default"] |
The image is placed at an X,Y coordinate relative to its parent image (such as the display). The coordinates specify the location
that the anchor pixel should be located on that image. The 0,0 point on the parent is the northwest corner of the parent.
| The image on which this image is rendered. |
| Type | attribute |
| Default | "Display.Primary" |
| The X position of the image anchor, relative to its parent. |
| Type | number |
| Default | 0 |
| The Y position of the image anchor, relative to its parent. |
| Type | number |
| Default | 0 |
| The stacking order value of this image. 0 is on the bottom. Images with a layer
value < 0 are not displayed. |
| Type | integer |
| Default | 0 |
| The alpha blending value of this image. 0.0 is transparent; 1.0 is
opaque. |
| Type | number |
| Default | 1.0 |
| The position of the anchor expressed as a compass
direction, or _C for center. For example, if the image is 150x24, anchor=_S would place the anchor at 75,24. |
| Type | enum
_N, _NW, _W, _SW, _S, _SE, _E, _NE, _C |
| Default | _NW |
| The width of the image. |
| Type | number |
| The displayed height of the image. Note that if the number of states is greater than 0, then the height reported in
this attribute will b |