Lab session given at OSCON Java 2011:
Visage is the successor to the JavaFX Script Language, a domain-specific language for writing UIs. It excels at rapid application design and can be used on any platform that supports Java. In this lab you will have an opportunity to write Visage applications that deploy to and run on Android mobile devices. No prior experience with Android or Visage development is required.
3. The Visage Language
§ Statically Compiled Language
§ Based on F3 / JavaFX Script
§ Planning Support for Different
Platforms:
- JavaFX 2.0
- Android
- Apache Pivot
> “Visage is a domain specific
language (DSL) designed for the - Flex
express purpose of writing user
interfaces.” - JSF
3
4. What Does Visage Look Like?
Stage {
var input:TextBox;
title: bind input.text
Scene {
input = TextBox {
color: #DDCC33
}
}
}
4
5. UI Focused Language Features
§ Declarative Object Construction
- Code looks like the UI it is representing.
§ Data Binding
- Variables can be bound to UI state, allowing automatic updates and
behavior to be triggered.
§ UI Definition Literals
- Built-in literal syntax for colors, angles, lengths, and durations
§ Null Safety
- Application logic will proceed even if intermediate variables are undefined
or null.
5
6. Visage on Android
§ Visage Runs as a Native App on Android
§ Full Access to all the Android APIs
§ Declarative Layer on Top of Android APIs
6
8. Exercise 1.A – Android Setup
§ Setup and run the VirtualBox image
§ Create an emulator instance
§ Create a new Android project from the command line
§ Run the project in the emulator
8
9. Setting Up Your Machine
1. Copy these files off the USB stick
(or from http://projavafx.com/VisageLab/):
- VirtualBox for your platform (Mac, Windows, or Linux)
- VisageLab folder
1. Decompress
VisageLab/Visage Dev2.vdi.zip
2. Install VirtualBox
3. Open Visage Dev.vbox
9
10. Set Up Your Device for Debugging
§ And mount it from:
- Devices > USB Devices > (your-device-name)
10
10
11. Or Create a Virtual Android Device
§ Launch the AVD Manager by typing: android
11
12. Setting Up Your Project
§ Project creation command:
- android create project –t 1 –p HelloVisage –k org.test –a HelloVisage
§ Arguments:
- n : Project name (optional)
- t : Target ID of the new project (required)
- p : Project directory (required)
- k : Package name for the application (required)
- a : Name of the default Activity (required)
12
14. Plus some more Java…
public class HelloVisage extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedIS) {
super.onCreate(savedIS);
setContentView(R.layout.main);
}
}
14
15. Run Your Project
§ cd HelloVisage
§ ant install
§ Open it in the applications menu
15
16. Exercise 1.B – All Java Conversion
§ Make sure you have the basic project running first
§ Convert the XML Code to Java
§ Run the all Java project
§ You should get identical results
16
17. Converted XML Code (simplified)
public class HelloVisage extends Activity {
@Override public void onCreate(Bundle savedIS) {
super.onCreate(savedIS);
Context context = getApplicationContext();
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
TextView text = new TextView(context);
text.setText("Hello World, Java Only");
layout.addView(text);
setContentView(layout);
}
}
17
18. (and here are the imports…)
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
18
19. Exercise 1.C – DDMS Debugging
§ So you made a mistake in your code… the compiler can’t catch
everything
- (even if you didn’t make a mistake, force one… a beautiful
NullPointerException will do)
§ Launch DDMS and select your emulator/device
19
20. Break the code (change in bold)
public class HelloVisage extends Activity {
@Override public void onCreate(Bundle savedIS) {
super.onCreate(savedIS);
Context context = getApplicationContext();
LinearLayout layout = null;//new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
TextView text = new TextView(context);
text.setText("Hello World, HelloVisage");
layout.addView(text);
setContentView(layout);
}
}
20
22. Exercise 1.D – Visage Port
§ Modify the build script to compile Visage
§ Copy the Visage Runtime libraries
§ Convert the Java code to Visage
§ Run on device/emulator
22
26. Copy Over the Runtime JAR
§ Copy:
- javafxrt.jar
§ From:
- $visagehome/lib/shared/
§ To:
- $projectdir/libs
26
27. Straight JavaFX Conversion...
public class Test extends Activity {
override function onCreate(savedInstanceState:Bundle) {
super.onCreate(savedInstanceState);
def context = getApplicationContext();
def layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
def text = new TextView(context);
text.setText("Hello World, Hello Long Visage");
layout.addView(text);
setContentView(layout);
}
}
27
35. Language Similarities
Java is… Visage is…
§ Statically typed § Statically typed
§ Compiled to bytecodes § Compiled to bytecodes
§ Runs on the JVM § Runs on the JVM
§ Has a large library § Can call Java libraries
35
37. Integrating Visage and Java
§ Calling Java from Visage
- Can call Java interface or classes directly
- Automatic conversion to and from Arrays and Collections
- Can even extend Java interfaces and classes
§ Calling Visage from Java
- Easiest way is to create a Java interface that Visage extends
- Can invoke Visage as a script and get results back
37
39. Datatype Support
DataType
Java Equivalent
Range
Examples
Boolean
boolean
true or false
true, false
Integer
int
-2147483648 to 2147483647
2009, 03731, 0x07d9
Number
Float
1.40×10-45 and 3.40×1038
3.14, 3e8, 1.380E-23
String
String
N/A
"java's", 'in"side"er'
Duration
<None>
-263 to 263-1 milliseconds
1h, 5m, 30s, 500ms
Length <None> dp, sp, em, %, mm, cm, in 2mm, 5sp, 1in
Angle <None> rad, deg, turn 1rad, 30deg
Color <None> #RRGGBB, #RGB, #CCCCCC, #202020|D0
#RRGGBB|AA, #RGB|A
Character
char
0 to 65535
0, 20, 32
Byte
byte
-128 to 127
-5, 0, 5
Short
short
-32768 to 32767
-300, 0, 521
Long
long
-263 to 263-1
2009, 03731, 0x07d9
Float
float
1.40×10-45 and 3.40×1038
3.14, 3e8, 1.380E-23
Double
double
4.94×10-324 and 1.80×10308
3.14, 3e231, 1.380E-123
39
40. Visage Operators
Operator
Meaning
Precedence
Examples
++
Pre/post increment
1
++i, i++
--
Pre/post decrement
1
--i, i--
not
Boolean negation
2
not (cond)
*
Multiply
3
2 * 5, 1h * 4
/
Divide
3
9 / 3, 1m / 3
mod
Modulo
3
20 mod 3
+
Add
4
0 + 2, 1m + 20s
-
Subtract (or negate)
4 (2)
-2, 32 -3, 1h -5m
> Multiplication and division of two durations is allowed, but not meaningful
> Underflows/Overflows will fail silently, producing inaccurate results
> Divide by zero will throw a runtime exception
40
41. Visage Operators (continued)
Operator
Meaning
Precedence
Examples
==
Equal
5
value1 == value2, 4 == 4
!=
Not equal
5
value1 != value2, 5 != 4
<
Lessthan
5
value1 < value2, 4 < 5
<=
Lessthanorequal
5
value1 <= value2, 5 <= 5
>
Greater than
5
value1 > value2, 6 > 5
>=
Greater than or equal
5
value1 >= value2, 6 >= 6
instanceof
Is instance of class
6
node instanceof Text
as
Typecast to class
6
node as Text
and
Boolean and
7
cond1 and cond2
or
Boolean or
8
cond1 or cond2
+=
Add and assign
9
value += 5
-=
Subtract and assign
9
value -= 3
*=
Multiply and assign
9
value *= 2
/=
Divide and assign
9
value /=4
=
Assign
9
value = 7
41
42. Access Modifiers
Modifier
Name
Description
<default>
Script only access
Only accessible within the same script file
package
Package access
Only accessible within the same package
protected
Protected access
Only accessible within the same package or by subclasses.
public
Public access
Can be accessed anywhere.
public-read
Read access modifier
Var/def modifier to allow a variable to be read anywhere
public-init
Init access modifier
Var/def modifier to allow a variable to be initialized or read anywhere
42
43. Data Binding
§ A variable or a constant can be bound to an expression
- var x = bind a + b;
§ The bound expression is remembered
§ The dependencies of the expression is watched
§ Variable is updated lazily when possible
43
48. Merging Build Scripts
§ Update the build.xml file:
Set the project name to “ConfigReporter”
§ Update the strings.xml file:
Set the app_name to “ConfigReporter”
§ Load the NetBeans property files (in build.xml):
<property file="nbproject/private/config.properties"/>
<property file="nbproject/private/configs/${config}.properties"/>
<property file="nbproject/private/private.properties"/>
<property file="${user.properties.file}"/>
<property file="nbproject/configs/${config}.properties"/>
<property file="nbproject/project.properties"/>
48
58. Exercise 2.E – Android Settings
§ Create a Settings Activity
§ Populate it with the following preferences:
- Text
- Password
- List
§ Launch it from the Button control
58
59. Settings Class
public class Settings extends PreferenceActivity {
var usernamePref:EditTextPreference;
var passwordPref:EditTextPreference;
var pollingPref:ListPreference;
override var screen = PreferenceScreen {
preferences: [
…
59
67. What Bind Updates
var x = bind if(a) then b else c
§ x is updated if a or b or c changes
var x = bind for (i in [a..b]) { i * i }
§ Not everything is recalculated
§ If a = 1 and b = 2, x is [1, 4]
§ If b changes to 3, only the added element is calculated
1 4 9
67
68. Binding to Expressions
§ Binding to a block
§ Bound block may contain any number of defs followed by one
expression
§ Dependencies of block is backtraced from the expression
§ Binding to function invocation expression
- Regular function: dependencies are parameters
- Bound function: backtraced from final expression inside function
68
69. Binding to Object Literals
var a = 3; var b = 4;
var p = bind Point { x: a, y: b };
var q = bind Point { x: bind a, y: b };
var r = bind Point { x: bind a, y: bind b };
§ When a changes:
- p gets a new instance of Point
- q and r keep the old instance with a new x value
- r will never get a new instance of Point
- (the outer bind in r is useless)
69
70. Visage Sequences
§ Represents collections of homogeneous data
§ A fundamental container data type
§ Rich set of language facilities
§ Contributor to declarative syntax
§ Automatic conversion to and from Java Arrays and Collections
70
71. Creating Sequences
§ Explicit sequence expression
- [1, 3, 5, 7, 9]
§ Elements are separated by commas
§ Comma may be omitted if element ends with brace
1 3 5 7 9
71
72. Creating Sequences
§ Numeric sequence with range expressions:
- [1..10] 1 2 3 4 5 6 7 8 9 10
§ Can have a step:
- [1..10 step 2] 1 3 5 7 9
- [0.0..0.9 step 0.1] 0 .1 .2 .3 .4 .5 .6 .7 .8 .9
§ Can be decreasing:
- [10..1 step -3] 10 7 4 1
§ Beware of step that goes opposite direction:
- [10..1] is []
§ Exclusive right end
- [1..<5] 1 2 3 4
73. Getting Info from Sequences
ints = [1, 3, 5, 7, 9]
1 3 5 7 9
[0] [1] [2] [3] [4]
§ sizeof ints is 5
§ ints[0] is 1, ints[1] is 3, ..., ints[4] is 9
§ ints[-1] is 0 (default value of Integer), so is ints[5]
§ For a sequence of objects, the default is null
73
74. Getting Slices from Sequences
ints = [1, 3, 5, 7, 9]
1 3 5 7 9
[0] [1] [2] [3] [4]
§ ints[0..2] is [1, 3, 5]
§ ints[0..<2] is [1, 3]
§ ints[2..] is [5, 7, 9]
§ ints[2..<] is [5, 7]
§ ints[2..0], ints[-2..-1], ints[5..6] are all []s
74
75. Getting Subsets from Sequences
ints = [1, 3, 5, 7, 9]
1 3 5 7 9
[0] [1] [2] [3] [4]
§ ints[k | k > 6] is:
- [7, 9] (k > 6 is a condition)
§ ints[k | indexof k < 2] is:
- [1, 3]
§ ints[k | k > 10] is:
- []
75
78. Sequence Puzzlers
What is the size of this sequence:
§ [1..10 step -1]
What does this evaluate to:
§ [10..<20 step 2][k|k>17]
What is the size of this sequence:
§ sizeof [20..1 step -3]