Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
-
Upload
stephen-chin -
Category
Technology
-
view
6.761 -
download
4
description
Transcript of Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
Cleaner APIs, Cleaner UIs with VisageStephen ChinChief Agile Methodologist – GXS
http://steveonjava.com/Tweet: @steveonjava
The Visage Language
2
Statically Compiled Language
Based on F3 / JavaFX Script
Planning Support for Different Platforms:- JavaFX 2.0- Vaadin- A Popular Linux-based
Tablet OS
> "Visage is a domain specific language (DSL) designed for the express purpose of writing user interfaces."
http://visage-lang.org/
What Does Visage Look Like?Stage { var input:TextBox; title: bind input.text Scene { input = TextBox { color: #DDCC33 } }}
3
What Does Visage Look Like?
4
Stage { var input:TextBox; title: bind input.text Scene { input = TextBox { color: #DDCC33 } }}
Hierarchy Models Your User Interface
Hierarchy Models Your User Interface
What Does Visage Look Like?
5
Stage { var input:TextBox; title: bind input.text Scene { input = TextBox { color: #DDCC33 } }}
User Interface Updates Automatically
User Interface Updates Automatically
What Does Visage Look Like?
6
Stage { var input:TextBox; title: bind input.text Scene { input = TextBox { color: #DDCC33 } }}
Built-in Constructs for Building UIs
Built-in Constructs for Building UIs
What Does Visage Look Like?
7
Stage { var input:TextBox; title: bind input.text Scene { input = TextBox { color: #DDCC33 } }}
No more NPEs!No more NPEs!
What Does Visage Look Like?
8
Stage { var input:TextBox; title: bind input!.text Scene { input = TextBox { color: #DDCC33 } }}
Unless you add an exclamation mark!Unless you add an exclamation mark!
9
JavaFX With Visage
Java vs. Visage DSLpublic class VanishingCircles extends Application {
public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Vanishing Circles"); Group root = new Group(); Scene scene = new Scene(root, 800, 600, Color.BLACK); List<Circle> circles = new ArrayList<Circle>(); for (int i = 0; i < 50; i++) { final Circle circle = new Circle(150); circle.setCenterX(Math.random() * 800); circle.setCenterY(Math.random() * 600); circle.setFill(new Color(Math.random(), Math.random(),
Math.random(), .2)); circle.setEffect(new BoxBlur(10, 10, 3)); circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new
EventHandler<MouseEvent>() { public void handle(MouseEvent t) { KeyValue collapse = new KeyValue(circle.radiusProperty(), 0); new Timeline(new KeyFrame(Duration.seconds(3), collapse)).play(); } }); circle.setStroke(Color.WHITE); circle.strokeWidthProperty().bind(Bindings.when(circle.hoverProperty()) .then(4) .otherwise(0)); circles.add(circle); } root.getChildren().addAll(circles); primaryStage.setScene(scene); primaryStage.show(); Timeline moveCircles = new Timeline(); for (Circle circle : circles) { KeyValue moveX = new KeyValue(circle.centerXProperty(), Math.random() *
800); KeyValue moveY = new KeyValue(circle.centerYProperty(), Math.random() *
600); moveCircles.getKeyFrames().add(new KeyFrame(Duration.seconds(40), moveX,
moveY)); } moveCircles.play(); }}
var circles:Circle[];Stage { title: "Vanishing Circles" Scene { width: 800 height: 600 fill: BLACK Group { circles = for (i in [1..50]) { def c:Circle = Circle { centerX: random() * 800 centerY: random() * 600 radius: 150 fill: color(random(), random(), random(), .2) effect: BoxBlur { height: 10 width: 10 iterations: 3 } stroke: WHITE strokeWidth: bind if (c.hover) 5 else 0 onMouseClicked: function(e) { Timeline {at (3s) {c.radius => 0}}.play() } } } } }}
Timeline { for (circle in circles) at (40s) { circle.centerX => random() * 800; circle.centerY => random() * 600 }}.play()
10
40 Lines1299 Characters40 Lines1299 Characters
35 Lines487 Characters35 Lines487 Characters
How about JavaFX on… VisageStage { title: "Vanishing Circles" scene: Scene { width: 800 height: 600 fill: BLACK content: Group { circles = for (i in [1..50]) { Circle { centerX: random() * 800 centerY: random() * 600 } } } }}
11
How about JavaFX on… VisageStage { title: "Vanishing Circles" scene: Scene { width: 800 height: 600 fill: BLACK content: Group { circles = for (i in [1..50]) { Circle { centerX: random() * 800 centerY: random() * 600 } } } }}
12
How about JavaFX on… VisageStage { title: "Vanishing Circles" Scene { width: 800 height: 600 fill: BLACK Group { circles = for (i in [1..50]) { Circle { centerX: random() * 800 centerY: random() * 600 } } } }}
13
Vanishing Circles Demo
Visage is JavaFX Script++Default ParametersNew Literal Syntax For:- Angles – 35deg, 4rad, 1turn
- Colors – #DDCCBB, #AA33AA|CC
- Lengths – 5px, 2pt, 3in, 4spNull-check Dereference- var width = rect.!width
Built-in Bindable Maps (coming soon!)- var fruitMap = ["red" : apple, "yellow" : banana]
- var fruit = bind fruitMap["red"]
15
And Made for JavaFX 2.0…Enhanced Binding- Retains lazy evaluation properties with additional
expressive power Integrated Collections- Sequences and Maps automatically convert between
JavaFX Observable Lists/MapsBuilt-in Animation Syntax- Ties into JavaFX animation subsystem
- Provides consistent, clean APIs
16
Why VaadinRich Set of UI Controls
Java->Javascript Compiler- Write Custom UI Components in Visage
Vaadin Brings Visage to the Web!
Java Vaadin Applicationpublic class SimpleApplication extends Application {
@Override
public void init() {
Window mainWindow = new Window("Simple Application");
Label label = new Label("Hello 33rd Degrees!");
mainWindow.addComponent(label);
setMainWindow(mainWindow);
}
}
19
Visage Vaadin Application (unoptimized)
public class VisagevaadinApplication extends Application {
override function init() {
def mainWindow = new Window("Unoptimized Visage Vaadin Application");
def label = new Label("Hello Visage User");
mainWindow.addComponent(label);
setMainWindow(mainWindow);
}
}
20
Visage Vaadin Application (optimized!)
public class VisagevaadinApplication2 extends Application {
override var window = Window {
caption: "Optimized Visage Vaadin Application"
Label {
content: "Hello Expert Visage Coder"
}
}
}
21
Visage Vaadin Address Book Demo
A Popular Linux-based Tablet OS With VISAGE
Visage on Android
24
Visage Runs as a Native App on AndroidFull Access to all the Android APIsDeclarative Layer on Top of Android APIs
Hello World, Visage
Demo 1
25
Android XML Code<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" ><TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, HelloVisage" /></LinearLayout>
26
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);
}
}
27
All Java Conversion
28
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); }}
29
Visage Port
30
Straight JavaFX Conversion...public class HelloVisage 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, Long Visage"); layout.addView(text); setContentView(layout); }}
31
Straight JavaFX Conversion...public class HelloVisage 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, Long Visage"); layout.addView(text); setContentView(layout); }}
32
Override is a built-in keyword
Override is a built-in keyword
Straight JavaFX Conversion...public class HelloVisage 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, Long Visage"); layout.addView(text); setContentView(layout); }}
33
Functions begin with the keyword "function"
Functions begin with the keyword "function"
Straight JavaFX Conversion...public class HelloVisage 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, Long Visage"); layout.addView(text); setContentView(layout); }}
34
Type after variable (separated by colon)Type after variable
(separated by colon)
Straight JavaFX Conversion...public class HelloVisage 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, Long Visage"); layout.addView(text); setContentView(layout); }}
35
Variables declarations start with "def" or "var"Variables declarations start with "def" or "var"
Android JavaFX Codepublic class HelloVisage extends Activity {
override var view = LinearLayout {
orientation: Orientation.VERTICAL
view: TextView {
text: "Hello World, Beautified Visage"
}
}
}
36
Working Hello Visage Application
37
CONTROLS AND SETTINGS
Demo 2
38
Android ControlsCreate a Text FieldCreate an Edit BoxWire them up using Binding
39
Bound Controls (1)override var view = LinearLayout {
orientation: Orientation.VERTICAL
var secret:String;
view: [
EditText {
hint: "Super Secret Text"
password: true
text: bind secret with inverse
40
Bound Controls (2) }
TextView {
text: "Is Revealed!!!"
}
TextView {
text: bind secret
}
]
}
41
Button HandlerCreate a Button ControlAdd an onClick handlerMake something happen (maybe a bind)
42
Button onClick handlerButton { text: "Launch Settings" onClick: function() { startActivity(new Intent(this, Settings.class)); setting = "Launching..."; }}TextView { text: "Setting is:"}TextView { text: bind setting}
43
Android SettingsCreate a Settings ActivityPopulate it with the following preferences:- Text
- Password
- ListLaunch it from the Button control
44
Settings Classpublic class Settings extends PreferenceActivity {
var usernamePref:EditTextPreference;
var passwordPref:EditTextPreference;
var pollingPref:ListPreference;
override var screen = PreferenceScreen {
preferences: [
…
45
Text PreferencePreferenceCategory {
title: "Preferences"
preferences: [
usernamePref = EditTextPreference {
title: "Username"
key: "usernamePref"
summary: bind if (usernamePref.text == "") "Currently undefined" else "Current value: {usernamePref.text}"
}46
Password PreferencepasswordPref = EditTextPreference {
title: "Password"
key: "passwordPref"
summary: bind passwordPref.text.replaceAll(".", "*");
}
47
List PreferencepollingPref = ListPreference { title: "Polling Interval" key: "pollingPref" defaultValue: "60000" entries: ["30 seconds", "1 minute", "5 minutes", "10 minutes", "15 minutes", "30 minutes", "1 hour"] entryValues: ["30000", "60000", "300000", "600000", "900000", "1800000", "3600000"] summary: bind pollingPref.entry}
48
Working Settings Panel
49
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]
Thank You!Stephen Chinhttp://steveonjava.comTweet: @steveonjava
Visage Project: http://visage-lang.org/
51
Visage Language Fundamentals
Lesson 1
52
Datatype Support
53
Visage Operators
54
> 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
Visage Operators (continued)
55
Access Modifiers
56
Data BindingA variable or a constant can be bound to an
expression- var x = bind a + b;
The bound expression is rememberedThe dependencies of the expression is watchedVariable is updated lazily when possible
57
What Bind Updatesvar x = bind if(a) then b else cx 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
58
11 44 99
Binding to ExpressionsBinding to a blockBound block may contain any number of defs
followed by one expressionDependencies of block is backtraced from the
expressionBinding to function invocation expression- Regular function: dependencies are parameters
- Bound function: backtraced from final expression inside function
59
Binding to Object Literalsvar 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)
60
Integrating Visage and JavaCalling Java from Visage- Can call Java interface or classes directly
- Automatic conversion to and from Arrays and Collections
- Can even extend Java interfaces and classesCalling Visage from Java- Easiest way is to create a Java interface that Visage
extends
- Can invoke Visage as a script and get results back
61
Advanced Javafx sequences
Lesson 2
62
Visage SequencesRepresents collections of homogeneous dataA fundamental container data typeRich set of language facilitiesContributor to declarative syntaxAutomatic conversion to and from Java Arrays
and Collections
63
Creating SequencesExplicit sequence expression- [1, 3, 5, 7, 9]
Elements are separated by commasComma may be omitted if element ends with
brace
64
11 33 55 77 99
Creating SequencesNumeric sequence with range expressions:- [1..10]
Can have a step:- [1..10 step 2]- [0.0..0.9 step 0.1]
Can be decreasing:- [10..1 step -3]
Beware of step that goes opposite direction:- [10..1] is []
Exclusive right end- [1..<5]
11 22 33 44 55 66 77 88 99 1010
11 33 55 77 99
00 .1.1 .2.2 .3.3 .4.4 .5.5 .6.6 .7.7 .8.8 .9.9
1010 77 44 11
11 22 33 44
Getting Info from Sequencesints = [1, 3, 5, 7, 9]
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]
Object sequence has a default of null
66
11 33 55 77 99[0] [1] [2] [3] [4]
Getting Slices from Sequencesints = [1, 3, 5, 7, 9]
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
67
11 33 55 77 99[0] [1] [2] [3] [4]
Getting Subsets from Sequencesints = [1, 3, 5, 7, 9]
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:- []
68
11 33 55 77 99[0] [1] [2] [3] [4]
Inserting into Sequencesints = [1, 3, 5, 7, 9]
insert 20 into ints
insert 30 before ints[2]
insert 40 after ints[4]
insert [50, 60] into ints
11 33 55 77 99
11 33 55 77 99
11 33 55 77 99
2020
20203030
11 33 55 77 99 20203030 4040
11 33 55 77 99 20203030 4040 5050 6060
Deleting from Sequences ints = [1, 3, 5, 7, 9]
delete 7 from ints
delete ints[0]
delete ints[0..1]
delete ints: ints becomes []
11 33 55 77 99
11 33 55 99
33 55 99
99
11 33 55 77 99