cleaner apis, cleaner uis with visage (33rd degrees)

Post on 12-May-2015

6.762 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

Visage is a JVM language designed specifically for UI development, with special syntax for hierarchically describing UIs, binding data and behavior, and representing UI specific concepts such as animation, layout, and styles. It also is a full-featured language with a full compiler tool-chain, static compilation to JVM bytecodes, and IDE plug-ins. This talk will demonstrate how to use the Visage language to build UIs for JavaFX 2.0, Vaadin, and Android. Find out how you can take control of your UI development by writing cleaner, more maintainable UI code using the Visage language in your existing Java projects.

TRANSCRIPT

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

top related