UiPath Community: Communication Mining from Zero to Hero
GWT + HTML5: Add Visualizations via Canvas
1. GWT + HTML5
GTUG Atlanta
David Chandler drfibonacci@google.com
Philip Rogers pdr@google.com
Thursday, June 30, 2011 1
2. Agenda
• Overview
• Local Storage for performance
• Visualizations via Canvas
• Enrich your app with Audio
• Embedding Video in your app
• Drag and Drop support
• Handling unsupported browser versions
• CSS3 makes its way into GWT
• Angry Birds / ForPlay
Thursday, June 30, 2011 2
3. Overview
• What to expect
o Lots of demos
o Lots of code examples
• What you will learn
o How to use HTML5 in your GWT app
Thursday, June 30, 2011 3
4. Overview
What is HTML5?
• HTML5 includes lots of stuff
o Media rich DOM elements
o Useful new APIs
o CSS3 enhancements
• Support is increasing very rapidly
• Embrace it to make your apps stand out
Thursday, June 30, 2011 4
7. HTML5 for Designers
header,nav,footer -- more semantic meaning
aside concept
HSL color
@font-face
border-radius
transforms, transitions
Canvas
HTML5 video player (sans Flash)
Thursday, June 30, 2011 7
8. HTML5 for Programmers
• WebSockets
• Client-side storage
o LocalStorage API
o Web SQL (it's dead, Jim)
o indexedDB
• Web Workers
• form fields
o type=email,date,range,search,tel,color,...
• <meter>,<progress>
• app cache
• notifications
• geolocation
• device orientation
• server side events
Thursday, June 30, 2011 8
9. HTML5 support
http://www.html5rocks.com/
http://html5test.com
Thursday, June 30, 2011 9
10. Agenda
• Overview
• Local Storage for performance
• Visualizations via Canvas
• Enrich your app with Audio
• Embedding Video in your app
• Drag and Drop support
• Handling unsupported browser versions
• CSS3 makes its way into GWT
• Angry Birds / ForPlay
Thursday, June 30, 2011 10
11. Local Storage
Isn't it just a cookie?
Thursday, June 30, 2011 11
12. Local Storage
Isn't it just a cookie?
• Cookies are sent with each request!
• Local storage provides MBs worth of storage
• Local storage can be shared between browser windows
Thursday, June 30, 2011 12
13. Local Storage
Available in GWT
• GWT provides a Storage API
Storage storage = Storage.getLocalStorageIfSupported();
if (storage != null) {
storage.setItem("foo", "bar");
}
Storage storage = Storage.getLocalStorageIfSupported();
if (storage != null) {
String value = storage.getItem("foo");
}
Thursday, June 30, 2011 13
14. Local Storage
Available in GWT
• GWT provides a Storage API
Storage storage = Storage.getLocalStorageIfSupported();
if (storage != null) {
storage.setItem("foo", "bar");
}
Storage storage = Storage.getLocalStorageIfSupported();
if (storage != null) {
String value = storage.getItem("foo");
}
Thursday, June 30, 2011 14
15. Local Storage
Available in GWT
• GWT provides a Storage API
Storage storage = Storage.getLocalStorageIfSupported();
if (storage != null) {
storage.setItem("foo", "bar");
}
Storage storage = Storage.getLocalStorageIfSupported();
if (storage != null) {
String value = storage.getItem("foo");
}
Thursday, June 30, 2011 15
16. Local Storage
Available in GWT
• StorageMap lets you access storage using a java.util.Map
o Contributions by Bart Guijt
Storage storage = Storage.getLocalStorageIfSupported();
if (storage != null) {
StorageMap map = new StorageMap(storage);
storage.put("foo", "bar");
}
Thursday, June 30, 2011 16
17. Local Storage
For improved performance
• Cache data from RPC calls
• Load cached data on startup for faster startup times
Thursday, June 30, 2011 17
18. Local Storage
For improved performance
• Cache data from RPC calls
• Load cached data on startup for faster startup times
Thursday, June 30, 2011 18
19. Local Storage
For improved performance
Demo
Thursday, June 30, 2011 19
20. Local Storage
For improved user experience
• Save temporary state to local storage
• Restore state when user re-enters app
• Prevent lost work on network disconnect
Thursday, June 30, 2011 20
21. Agenda
• Overview
• Local Storage for performance
• Visualizations via Canvas
• Enrich your app with Audio
• Embedding Video in your app
• Drag and Drop support
• Handling unsupported browser versions
• CSS3 makes its way into GWT
• Angry Birds / ForPlay
Thursday, June 30, 2011 21
22. Canvas
Adding visualizations to your app
• This slide is boring
Past Due 3
Due Tomorrow 1
On Time 1
No Due Date 6
Thursday, June 30, 2011 22
23. Canvas
Adding visualizations to your app
• Charts bring data to life
• Canvas brings charts to the web
Thursday, June 30, 2011 23
24. Canvas
Adding visualizations to your app
Demo
Thursday, June 30, 2011 24
25. Canvas
Adding visualizations to your app
1. Initialize the canvas
2. Calculate values for new shapes
3. Clear the current canvas
4. Draw the new shapes
Thursday, June 30, 2011 25
26. // Initialize the canvas.
final Canvas canvas = Canvas.createIfSupported();
canvas.setCoordinateSpaceHeight(300);
canvas.setCoordinateSpaceWidth(300);
canvas.setPixelSize(300, 300);
// Get the dimensions of the canvas.
int width = canvas.getCoordinateSpaceWidth();
int height = canvas.getCoordinateSpaceHeight();
double radius = Math.min(width, height) / 2.0;
double cx = width / 2.0;
double cy = height / 2.0;
// Clear the context.
Context2d context = canvas.getContext2d();
context.clearRect(0, 0, width, height);
// Draw a filled arc.
context.setFillStyle(CssColor.make(255, 211, 25));
context.beginPath();
context.moveTo(cx, cy);
context.arc(cx, cy, radius, 0, Math.PI);
context.fill();
Thursday, June 30, 2011 26
27. // Initialize the canvas.
final Canvas canvas = Canvas.createIfSupported();
canvas.setCoordinateSpaceHeight(300);
canvas.setCoordinateSpaceWidth(300);
canvas.setPixelSize(300, 300);
// Get the dimensions of the canvas.
int width = canvas.getCoordinateSpaceWidth();
int height = canvas.getCoordinateSpaceHeight();
double radius = Math.min(width, height) / 2.0;
double cx = width / 2.0;
double cy = height / 2.0;
// Clear the context.
Context2d context = canvas.getContext2d();
context.clearRect(0, 0, width, height);
// Draw a filled arc.
context.setFillStyle(CssColor.make(255, 211, 25));
context.beginPath();
context.moveTo(cx, cy);
context.arc(cx, cy, radius, 0, Math.PI);
context.fill();
Thursday, June 30, 2011 27
28. // Initialize the canvas.
final Canvas canvas = Canvas.createIfSupported();
canvas.setCoordinateSpaceHeight(300);
canvas.setCoordinateSpaceWidth(300);
canvas.setPixelSize(300, 300);
// Get the dimensions of the canvas.
int width = canvas.getCoordinateSpaceWidth();
int height = canvas.getCoordinateSpaceHeight();
double radius = Math.min(width, height) / 2.0;
double cx = width / 2.0;
double cy = height / 2.0;
// Clear the context.
Context2d context = canvas.getContext2d();
context.clearRect(0, 0, width, height);
// Draw a filled arc.
context.setFillStyle(CssColor.make(255, 211, 25));
context.beginPath();
context.moveTo(cx, cy);
context.arc(cx, cy, radius, 0, Math.PI);
context.fill();
Thursday, June 30, 2011 28
29. // Initialize the canvas.
final Canvas canvas = Canvas.createIfSupported();
canvas.setCoordinateSpaceHeight(300);
canvas.setCoordinateSpaceWidth(300);
canvas.setPixelSize(300, 300);
// Get the dimensions of the canvas.
int width = canvas.getCoordinateSpaceWidth();
int height = canvas.getCoordinateSpaceHeight();
double radius = Math.min(width, height) / 2.0;
double cx = width / 2.0;
double cy = height / 2.0;
// Clear the context.
Context2d context = canvas.getContext2d();
context.clearRect(0, 0, width, height);
// Draw a filled arc.
context.setFillStyle(CssColor.make(255, 211, 25));
context.beginPath();
context.moveTo(cx, cy);
context.arc(cx, cy, radius, 0, Math.PI);
context.fill();
Thursday, June 30, 2011 29
30. Canvas
Adding visualizations to your app
• Canvas has a coordinate space separate from DOM size
• Coordinate space is scaled to the DOM size
o Small coordinate space = faster performance
o Large coordinate space = higher quality
• Match coordinate space to DOM size
o Assign a fixed size to the DOM element, or
o Catch resize events and adjust the coordinate space
300x300 30x30
Thursday, June 30, 2011 30
31. Agenda
• Overview
• Local Storage for performance
• Visualizations via Canvas
• Enrich your app with Audio
• Embedding Video in your app
• Drag and Drop support
• Handling unsupported browser versions
• CSS3 makes its way into GWT
• Angry Birds / ForPlay
Thursday, June 30, 2011 31
32. Audio
• Embed audio using the Audio widget
• Play a sound or stream
Thursday, June 30, 2011 32
34. Audio
• Format support varies across browsers
• Choose at least two of the three main formats
Ogg Vorbis MP3 WAV
Chrome ✓ ✓
Firefox ✓ ✓
Internet
Explorer ✓ ✓
Opera ✓ ✓
Safari ✓ ✓
Source: http://html5doctor.com/native-audio-in-the-browser/
Thursday, June 30, 2011 34
35. Audio
Specify multiple sources
• You can specify multiple sources in HTML5
• Don't forget the "type" attribute
o Browsers will load all source files
o Must load meta data to detect mime-type
o Cannot assume mime-type from file extension
<audio controls>
<source src="path/file.ogg" type="audio/ogg" />
<source src="path/file.mp3" type="audio/mpeg" />
<source src="path/file.wav" type="audio/wav" />
</audio>
Thursday, June 30, 2011 35
36. Audio
Specify multiple sources (2.4)
public Audio createAudio() {
Audio audio = Audio.createIfSupported();
if (audio == null) {
return;
}
audio.addSource("path/file.ogg", AudioElement.TYPE_OGG);
audio.addSource("path/file.mp3", AudioElement.TYPE_MP3);
audio.addSource("path/file.wav", AudioElement.TYPE_WAV);
// Show audio controls.
audio.setControls(true);
return audio;
}
Thursday, June 30, 2011 36
37. Audio
Specify multiple sources (2.4)
public Audio createAudio() {
Audio audio = Audio.createIfSupported();
if (audio == null) {
return;
}
audio.addSource("path/file.ogg", AudioElement.TYPE_OGG);
audio.addSource("path/file.mp3", AudioElement.TYPE_MP3);
audio.addSource("path/file.wav", AudioElement.TYPE_WAV);
// Show audio controls.
audio.setControls(true);
return audio;
}
Thursday, June 30, 2011 37
38. Audio
Specify multiple sources (2.4)
public Audio createAudio() {
Audio audio = Audio.createIfSupported();
if (audio == null) {
return;
}
audio.addSource("path/file.ogg", AudioElement.TYPE_OGG);
audio.addSource("path/file.mp3", AudioElement.TYPE_MP3);
audio.addSource("path/file.wav", AudioElement.TYPE_WAV);
// Show audio controls.
audio.setControls(true);
return audio;
}
Thursday, June 30, 2011 38
39. Audio
Specify multiple sources (2.4)
public Audio createAudio() {
Audio audio = Audio.createIfSupported();
if (audio == null) {
return;
}
audio.addSource("path/file.ogg", AudioElement.TYPE_OGG);
audio.addSource("path/file.mp3", AudioElement.TYPE_MP3);
audio.addSource("path/file.wav", AudioElement.TYPE_WAV);
// Show audio controls.
audio.setControls(true);
return audio;
}
Thursday, June 30, 2011 39
40. Audio
Manually choose the source
• You can ask the browser which files it might support
o Tells you "probably", "maybe", or ""
• Ensures that you only load that source
Thursday, June 30, 2011 40
41. public Audio createAudio() {
Audio audio = Audio.createIfSupported();
if (audio == null) {
return;
}
if (MediaElement.CAN_PLAY_PROBABLY.equals(
audio.canPlayType(AudioElement.TYPE_OGG)) {
audio.setSrc("path/file.ogg");
} else if (MediaElement.CAN_PLAY_PROBABLY.equals(
audio.canPlayType(AudioElement.TYPE_MP3)) {
audio.setSrc("path/file.mp3");
} else if (MediaElement.CAN_PLAY_MAYBE.equals(
audio.canPlayType(AudioElement.TYPE_OGG)) {
audio.setSrc("path/file.mp3");
} else if (MediaElement.CAN_PLAY_MAYBE.equals(
audio.canPlayType(AudioElement.TYPE_MP3)) {
audio.setSrc("path/file.mp3");
}
return audio;
}
Thursday, June 30, 2011 41
42. public Audio createAudio() {
Audio audio = Audio.createIfSupported();
if (audio == null) {
return;
}
if (MediaElement.CAN_PLAY_PROBABLY.equals(
audio.canPlayType(AudioElement.TYPE_OGG)) {
audio.setSrc("path/file.ogg");
} else if (MediaElement.CAN_PLAY_PROBABLY.equals(
audio.canPlayType(AudioElement.TYPE_MP3)) {
audio.setSrc("path/file.mp3");
} else if (MediaElement.CAN_PLAY_MAYBE.equals(
audio.canPlayType(AudioElement.TYPE_OGG)) {
audio.setSrc("path/file.mp3");
} else if (MediaElement.CAN_PLAY_MAYBE.equals(
audio.canPlayType(AudioElement.TYPE_MP3)) {
audio.setSrc("path/file.mp3");
}
return audio;
}
Thursday, June 30, 2011 42
43. Audio
Preloading a file
• Let the browser decide when to preload
Audio audio = Audio.createIfSupported();
audio.setSrc("path/file.ogg");
audio.setPreload(MediaElement.PRELOAD_AUTO);
• Or force the browser to preload
Audio audio = Audio.createIfSupported();
audio.setSrc("path/file.ogg");
audio.load();
Thursday, June 30, 2011 43
44. Audio
Preloading a file
• Let the browser decide when to preload
Audio audio = Audio.createIfSupported();
audio.setSrc("path/file.ogg");
audio.setPreload(MediaElement.PRELOAD_AUTO);
• Or force the browser to preload
Audio audio = Audio.createIfSupported();
audio.setSrc("path/file.ogg");
audio.load();
Thursday, June 30, 2011 44
45. Audio
Preloading a file
• Let the browser decide when to preload
Audio audio = Audio.createIfSupported();
audio.setSrc("path/file.ogg");
audio.setPreload(MediaElement.PRELOAD_AUTO);
• Or force the browser to preload
Audio audio = Audio.createIfSupported();
audio.setSrc("path/file.ogg");
audio.load();
Thursday, June 30, 2011 45
46. Agenda
• Overview
• Local Storage for performance
• Visualizations via Canvas
• Enrich your app with Audio
• Embedding Video in your app
• Drag and Drop support
• Handling unsupported browser versions
• CSS3 makes its way into GWT
• Angry Birds / ForPlay
Thursday, June 30, 2011 46
47. Video
• Embed videos using the Video widget
• Play a static video or a stream
Thursday, June 30, 2011 47
49. Video
• Format support varies across browsers
• Choose at least two of the three main formats
o Safari only supports mp4
Ogg Vorbis MP4 WebM
Chrome ✓ ✓
Firefox ✓ ✓
Internet
Explorer ✓
Opera ✓ ✓
Safari ✓
Source: http://en.wikipedia.org/wiki/HTML5_video
Thursday, June 30, 2011 49
50. Video
public Video createVideo() {
Video video = Video.createIfSupported();
if (video == null) {
return null;
}
video.addSource("path/file.ogg", VideoElement.TYPE_OGG);
video.addSource("path/file.mp4", VideoElement.TYPE_MP4);
video.addSource("path/file.webm", VideoElement.TYPE_WEBM);
// Show audio controls.
video.setControls(true);
return video;
}
Thursday, June 30, 2011 50
51. Video
public Video createVideo() {
Video video = Video.createIfSupported();
if (video == null) {
return null;
}
video.addSource("path/file.ogg", VideoElement.TYPE_OGG);
video.addSource("path/file.mp4", VideoElement.TYPE_MP4);
video.addSource("path/file.webm", VideoElement.TYPE_WEBM);
// Show audio controls.
video.setControls(true);
return video;
}
Thursday, June 30, 2011 51
52. Video
public Video createVideo() {
Video video = Video.createIfSupported();
if (video == null) {
return null;
}
video.addSource("path/file.ogg", VideoElement.TYPE_OGG);
video.addSource("path/file.mp4", VideoElement.TYPE_MP4);
video.addSource("path/file.webm", VideoElement.TYPE_WEBM);
// Show audio controls.
video.setControls(true);
return video;
}
Thursday, June 30, 2011 52
53. Video
public Video createVideo() {
Video video = Video.createIfSupported();
if (video == null) {
return null;
}
video.addSource("path/file.ogg", VideoElement.TYPE_OGG);
video.addSource("path/file.mp4", VideoElement.TYPE_MP4);
video.addSource("path/file.webm", VideoElement.TYPE_WEBM);
// Show audio controls.
video.setControls(true);
return video;
}
Thursday, June 30, 2011 53
54. Agenda
• Overview
• Local Storage for performance
• Visualizations via Canvas
• Enrich your app with Audio
• Embedding Video in your app
• Drag and Drop support
• Handling unsupported browser versions
• CSS3 makes its way into GWT
• Angry Birds / ForPlay
Thursday, June 30, 2011 54
55. Drag and Drop
• Move stuff around... with style
• Associate text or ID with the event
• Many types of drag events
Thursday, June 30, 2011 55
57. Drag and Drop
Make a widget draggable
• Set the "draggable" attribute to "true"
• Add a DragStart handler
• Set data in the DragStart handler
Thursday, June 30, 2011 57
58. Drag and Drop
Make a widget draggable
// Make the widget draggable.
Label w = new Label("Drag Me");
w.getElement().setDraggable(Element.DRAGGABLE_TRUE);
// Add a DragStartHandler.
w.addDragStartHandler(new DragStartHandler() {
public void onDragStart(DragStartEvent event) {
// Required: set data for the event.
event.setData("text", "Hello World");
// Optional: show a copy of the widget under cursor.
event.getDataTransfer().setDragImage(w.getElement(),
10, 10);
}
});
Thursday, June 30, 2011 58
59. Drag and Drop
Make a widget draggable
// Make the widget draggable.
Label w = new Label("Drag Me");
w.getElement().setDraggable(Element.DRAGGABLE_TRUE);
// Add a DragStartHandler.
w.addDragStartHandler(new DragStartHandler() {
public void onDragStart(DragStartEvent event) {
// Required: set data for the event.
event.setData("text", "Hello World");
// Optional: show a copy of the widget under cursor.
event.getDataTransfer().setDragImage(w.getElement(),
10, 10);
}
});
Thursday, June 30, 2011 59
60. Drag and Drop
Make a widget draggable
// Make the widget draggable.
Label w = new Label("Drag Me");
w.getElement().setDraggable(Element.DRAGGABLE_TRUE);
// Add a DragStartHandler.
w.addDragStartHandler(new DragStartHandler() {
public void onDragStart(DragStartEvent event) {
// Required: set data for the event.
event.setData("text", "Hello World");
// Optional: show a copy of the widget under cursor.
event.getDataTransfer().setDragImage(w.getElement(),
10, 10);
}
});
Thursday, June 30, 2011 60
61. Drag and Drop
Make a widget draggable
// Make the widget draggable.
Label w = new Label("Drag Me");
w.getElement().setDraggable(Element.DRAGGABLE_TRUE);
// Add a DragStartHandler.
w.addDragStartHandler(new DragStartHandler() {
public void onDragStart(DragStartEvent event) {
// Required: set data for the event.
event.setData("text", "Hello World");
// Optional: show a copy of the widget under cursor.
event.getDataTransfer().setDragImage(w.getElement(),
10, 10);
}
});
Thursday, June 30, 2011 61
62. Drag and Drop
Make a widget draggable
// Make the widget draggable.
Label w = new Label("Drag Me");
w.getElement().setDraggable(Element.DRAGGABLE_TRUE);
// Add a DragStartHandler.
w.addDragStartHandler(new DragStartHandler() {
public void onDragStart(DragStartEvent event) {
// Required: set data for the event.
event.setData("text", "Hello World");
// Optional: show a copy of the widget under cursor.
event.getDataTransfer().setDragImage(w.getElement(),
10, 10);
}
});
Thursday, June 30, 2011 62
63. Drag and Drop
Create a target
• Add a DragOver handler
• Add a Drop handler
o Prevent default action
o Get the data from the transfer object
Thursday, June 30, 2011 63
64. Label target = new Label("Drag onto me");
// Required: You must add a DragOverHandler to
// create a target.
target.addDragOverHandler(new DragOverHandler() {
public void onDragOver(DragOverEvent event) {
target.getElement().setBackgroundColor("#ffa");
}
});
// Add a DropHandler.
target.addDropHandler(new DropHandler() {
public void onDrop(DropEvent event) {
// Prevent the native text drop.
event.preventDefault();
// Get the data out of the event.
String data = event.getData("text");
target.setText(data);
}
});
Thursday, June 30, 2011 64
65. Label target = new Label("Drag onto me");
// Required: You must add a DragOverHandler to
// create a target.
target.addDragOverHandler(new DragOverHandler() {
public void onDragOver(DragOverEvent event) {
target.getElement().setBackgroundColor("#ffa");
}
});
// Add a DropHandler.
target.addDropHandler(new DropHandler() {
public void onDrop(DropEvent event) {
// Prevent the native text drop.
event.preventDefault();
// Get the data out of the event.
String data = event.getData("text");
target.setText(data);
}
});
Thursday, June 30, 2011 65
66. Label target = new Label("Drag onto me");
// Required: You must add a DragOverHandler to
// create a target.
target.addDragOverHandler(new DragOverHandler() {
public void onDragOver(DragOverEvent event) {
target.getElement().setBackgroundColor("#ffa");
}
});
// Add a DropHandler.
target.addDropHandler(new DropHandler() {
public void onDrop(DropEvent event) {
// Prevent the native text drop.
event.preventDefault();
// Get the data out of the event.
String data = event.getData("text");
target.setText(data);
}
});
Thursday, June 30, 2011 66
67. Label target = new Label("Drag onto me");
// Required: You must add a DragOverHandler to
// create a target.
target.addDragOverHandler(new DragOverHandler() {
public void onDragOver(DragOverEvent event) {
target.getElement().setBackgroundColor("#ffa");
}
});
// Add a DropHandler.
target.addDropHandler(new DropHandler() {
public void onDrop(DropEvent event) {
// Prevent the native text drop.
event.preventDefault();
// Get the data out of the event.
String data = event.getData("text");
target.setText(data);
}
});
Thursday, June 30, 2011 67
68. Label target = new Label("Drag onto me");
// Required: You must add a DragOverHandler to
// create a target.
target.addDragOverHandler(new DragOverHandler() {
public void onDragOver(DragOverEvent event) {
target.getElement().setBackgroundColor("#ffa");
}
});
// Add a DropHandler.
target.addDropHandler(new DropHandler() {
public void onDrop(DropEvent event) {
// Prevent the native text drop.
event.preventDefault();
// Get the data out of the event.
String data = event.getData("text");
target.setText(data);
}
});
Thursday, June 30, 2011 68
69. Drag and Drop
On any widget
• Some widgets do not implement drag handlers
• You can always use addDomHandler() to add a handler
// Add a DragStartHandler.
w.addDomHandler(new DragStartHandler() {
public void onDragStart(DragStartEvent event) {
// Required: set data for the event.
event.setData("text", "Hello World");
// Optional: show a copy of the widget under cursor.
event.getDataTransfer().setDragImage(w.getElement,
10, 10);
}
}, DragStartEvent.getType());
Thursday, June 30, 2011 69
70. Drag and Drop
+ File API?
• Spec is still changing rapidly.
• Not in GWT (yet!)
File[] files = event.getDataTransfer().getFiles();
// read an entire file
String txt = FileReader.readAsBinaryString(files[0]);
// read a chunk of a file
Reader reader = new Reader();
Blob blob = files[0].slice(startingByte, length);
String txt = reader.readAsBinaryString(blob);
Thursday, June 30, 2011 70
71. Drag and Drop Uploader
Demo
Thursday, June 30, 2011 71
72. Agenda
• Overview
• Local Storage for performance
• Visualizations via Canvas
• Enrich your app with Audio
• Embedding Video in your app
• Drag and Drop support
• Handling unsupported browser versions
• CSS3 makes its way into GWT
• Angry Birds / ForPlay
Thursday, June 30, 2011 72
73. Partial Support
Because if all browsers supported it, it would be too easy
• GWT provides APIs that are not supported in all browsers
o Modern browsers gaining market share rapidly
• Implementors of PartialSupport provide two static methods:
o isSupported()
o createIfSupported()
"Compiles out" if on a non-supported permutation!
Thursday, June 30, 2011 73
74. Partial Support
Fallback to another implementation
public void showChart(AcceptsOneWidget panel,
ChartData data) {
Canvas canvas = Canvas.createIfSupported();
if (canvas == null) {
// Fallback to an image if Canvas isn't supported.
String imageUrl = encodeChartData(data);
panel.setWidget(new Image(imageUrl);
return;
}
// Create a canvas chart.
...
// Display the canvas.
panel.setWidget(canvas);
}
Thursday, June 30, 2011 74
75. Agenda
• Overview
• Local Storage for performance
• Visualizations via Canvas
• Enrich your app with Audio
• Embedding Video in your app
• Drag and Drop support
• Handling unsupported browser versions
• CSS3 makes its way into GWT
• Angry Birds / ForPlay
Thursday, June 30, 2011 75
76. CSS3
Style your GWT app
• Nothing special required for CSS3
o Rounded corners, drop shadows, animations, group opacity,
multiple backgrounds, 3D transforms, etc.
o No changes required for GWT's UIBinder
Thursday, June 30, 2011 76
77. CSS3 in GWT's Widgets
• As of GWT 2.3, widgets now use CSS3
• On legacy browsers, widgets will be "usable"
Example: Rounded Corners
Thursday, June 30, 2011 77
78. Agenda
• Overview
• Local Storage for performance
• Visualizations via Canvas
• Enrich your app with Audio
• Embedding Video in your app
• Drag and Drop support
• Handling unsupported browser versions
• CSS3 makes its way into GWT
• Angry Birds / ForPlay
Thursday, June 30, 2011 78
80. Angry Birds
An HTML5 GWT app
• Announced at Google IO 2011
• Built with a library called ForPlay
o Uses GWT for Java -> HTML5 step.
• Uses most of the technologies talked about here
o Canvas, Audio*, Storage, CSS3
o Prove it
Thursday, June 30, 2011 80
81. Angry Birds
An HTML5 GWT app
• Announced at Google IO 2011
• Built with a library called ForPlay
o Uses GWT for Java -> HTML5 step.
• Uses most of the technologies talked about here
o Canvas, Audio*, Storage, CSS3
o Prove it
• Check out the I/O talk:
Kick-Ass Game Programming
with Google Web Toolkit
• http://goo.gl/UZ4X4
Thursday, June 30, 2011 81
82. ForPlay
In 30 seconds
• Cross-platform library for games
o Cross-browser (HTML5): WebGL, Canvas, 3D CSS
o Android, Flash, and Java apps too
• Write and debug games using the ForPlay API, compile
onto many platforms.
• API includes cross-platform abstractions for startup,
asset management, input (keyboard, touch, mouse),
audio, graphics, physics engine (box2d), json parsing,
etc.
Thursday, June 30, 2011 82
83. ForPlay
An GWT library for games
• Some demos
o Joel Webber's XNA Platormer port
o Aquarium by Mohamed Ousgougou / SFEIR
o http://p4cdroid.appspot.com/
o more examples, including source at gwtforplay.com
• For more info or if you'd like to join in:
http://gwtforplay.com
Thursday, June 30, 2011 83
84. GWT + HTML5
GTUG Atlanta
David Chandler drfibonacci@google.com
Philip Rogers pdr@google.com
Thursday, June 30, 2011 84