| <?php |
| /******************************************************************************* |
| * Copyright (c) 2015 Eclipse Foundation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eric Poirier (Eclipse Foundation) - Initial implementation |
| *******************************************************************************/ |
| ?> |
| |
| <h1 class="article-title"><?php echo $pageTitle; ?></h1> |
| |
| <p> |
| <a |
| href="http://www.oracle.com/technetwork/java/javafx/overview/index.html">JavaFX</a> |
| is Java's new rich client platform. With JavaFX it is easy to |
| create modern graphical user interfaces. It has built-in support |
| for visual effects and animations, supports touch-aware devices |
| and it includes an API for data-binding and event propagation. |
| JavaFX is the official successor to Java Swing but it will |
| result in much better looking apps. |
| </p> |
| |
| <p> |
| <a href="http://www.xtend-lang.org">Xtend</a> is a statically |
| typed programming language developed at <a |
| href="http://eclipse.org/">Eclipse</a>. Based on Java, Xtend |
| removes the syntactic noise and adds the missing bits such as |
| type inference, lambda expressions, extension methods or |
| operator overloading. It is compiled to Java code and thus |
| integrates seamlessly with existing libraries and frameworks. |
| Xtend brings the fun back to Java programming without any |
| trade-off in terms of compatibility. Xtend's additional features |
| are a perfect match to the needs of a JavaFX programmer. It will |
| make your code shine the same way as a JavaFX application does. |
| In this article, I will demonstrate that with a couple of |
| examples.<br /> This article relates to Xtend version 2.4. |
| </p> |
| |
| <h3>Event Listeners</h3> |
| <p> |
| Each JavaFX <a |
| href="http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html"><code |
| class="prettyprint lang-xtend">Node</code></a> has a couple |
| of convenience methods to react on UI events such as mouse |
| clicks, key strokes or multi-touch gestures. In Java a mouse |
| click can for example be handled with the following code: |
| </p> |
| |
| <pre class="prettyprint lang-java"> |
| // Java code |
| Rectangle node = new Rectangle(); |
| node.setOnMouseClicked(new EventHandler<MouseEvent>() { |
| @Override |
| public void handle(MouseEvent event) { |
| System.out.println(event.getButton() + " button clicked"); |
| } |
| }); |
| </pre> |
| |
| <p> |
| Let's see how we can improve this code by using Xtend. First of |
| all, Xtend's type inference allows to skip the type when it can |
| be inferred from the context. So the |
| <code class="prettyprint lang-java">Rectangle</code> |
| construction becomes |
| </p> |
| |
| <pre class="prettyprint lang-xtend"> |
| val node = new Rectangle |
| </pre> |
| |
| <p>Note that semicolons can be skipped as well as empty |
| parentheses.</p> |
| |
| <p> |
| Anonymous classes with a single method such as the |
| <code class="prettyprint lang-xtend">EventHandler</code> |
| instance is a very common Java idiom. Xtend improves on this |
| significantly by allowing to use <a |
| href="http://www.eclipse.org/xtend/documentation.html#lambdas">lambda |
| expressions</a> instead. The type is inferred from the actual |
| context. In the example the expected type is an |
| <code>EventHandler<MouseEvent></code> |
| , so the lambda expression is automatically converted to this |
| type: |
| </p> |
| |
| <pre class="prettyprint lang-xtend"> |
| val node = new Rectangle |
| node.setOnMouseClicked([ |
| MouseEvent event | println(event.getButton + "button clicked") |
| ]) |
| </pre> |
| |
| <p> |
| The part |
| <code class="prettyprint lang-xtend">MouseEvent event |</code> |
| denotes the parameter list of the lambda. If the lambda has only |
| one parameter it can be skipped and it will be named |
| <code class="prettyprint lang-xtend">it</code> |
| . The parameter type is also inferred from the context, in this |
| case it must be |
| <code class="prettyprint lang-xtend">MouseEvent</code> |
| . Like |
| <code class="prettyprint lang-xtend">this</code> |
| you can omit |
| <code class="prettyprint lang-xtend">it</code> |
| as the receiver of feature call. Without the explicit parameter |
| the code looks like this: |
| </p> |
| |
| <pre class="prettyprint lang-xtend"> |
| val node = new Rectangle |
| node.setOnMouseClicked([ |
| println(getButton() + "button clicked") |
| ]) |
| </pre> |
| |
| <p> |
| Finally, Xtend has a <a |
| href="http://www.eclipse.org/xtend/documentation.html#featureCalls">shortcut |
| syntax for getters and setters</a>: Instead of |
| <code class="prettyprint lang-xtend">getButton()</code> |
| you can just write |
| <code class="prettyprint lang-xtend">button</code> |
| . Similarly, |
| <code class="prettyprint lang-xtend">setOnMouseClicked(arg)</code> |
| becomes |
| <code class="prettyprint lang-xtend">onMouseClicked = arg</code> |
| . Once again this is just syntactic sugar. The accessor methods |
| are still called. Our final result reads as: |
| </p> |
| |
| <pre class="prettyprint lang-xtend"> |
| val node = new Rectangle |
| node.onMouseClicked = [ |
| println(button + "button clicked") |
| ] |
| </pre> |
| |
| <p>This snippet of Xtend code is completely equivalent to the Java |
| version above. It is a lot shorter, but it is still easier to |
| understand as all the syntactic noise has been cut out. Still |
| everything is type-safe and well defined.</p> |
| |
| <h3>The With Operator vs Generated Builder Classes</h3> |
| |
| <p>Sometimes a JavaFX object has quite a lot of parameters to be |
| customized. Instead of implementing a new constructor with a |
| huge number of parameters for each use case, the JavaFX |
| developers generated builder classes with fluent APIs, e.g.</p> |
| |
| <pre class="prettyprint lang-java"> |
| // Java code |
| Rectangle rectangle = RectangleBuilder.create() |
| .width(80) |
| .height(30) |
| .fill(Color.BLUE) |
| .stroke(Color.RED) |
| .strokeWidth(1.2) |
| .arcWidth(12) |
| .arcHeight(12) |
| .build(); |
| </pre> |
| |
| <p> |
| In Xtend the generated boilerplate is not needed at all because |
| there is the <em>with</em> operator |
| <code class="prettyprint lang-xtend">=></code> |
| that binds the preceding argument to the parameter of a lambda |
| expression and executes the latter: |
| </p> |
| |
| <pre class="prettyprint lang-xtend"> |
| val rectangle = new Rectangle => [ |
| Rectangle r | |
| r.setWidth(80) |
| r.setHeight(30) |
| r.setFill(Color::BLUE) |
| r.setStroke(Color::RED) |
| r.setStrokeWidth(1.2) |
| r.setArcWidth(12) |
| r.setArcHeight(12) |
| ] |
| </pre> |
| |
| <p> |
| Using the implicit |
| <code class="prettyprint lang-xtend">it</code> |
| as closure parameter and the sugared setter call as explained |
| above our code becomes: |
| </p> |
| |
| <pre class="prettyprint lang-xtend"> |
| val rectangle = new Rectangle => [ |
| width = 80 |
| height = 30 |
| fill = Color::BLUE |
| stroke = Color::RED |
| strokeWidth = 1.2 |
| arcWidth = 12 |
| arcHeight = 12 |
| ] |
| </pre> |
| |
| <p> |
| Note that the Xtend code is shorter than the Java builder syntax |
| even though it does not require an extra builder class. In a |
| similar way, the <em>with</em> operator facilitates the creation |
| of object trees, e.g. subtrees of JavaFX's scene-graph. |
| </p> |
| |
| <h3>Extension Methods For High-Level Property Binding</h3> |
| |
| <p> |
| In JavaFX, the value of a property can be derived from other |
| properties by means of another fluent API for the calculation. |
| E.g. given two |
| <code class="prettyprint lang-xtend">DoubleProperties</code> |
| <code class="prettyprint lang-xtend">a</code> |
| and |
| <code class="prettyprint lang-xtend">b</code> |
| , you can bind a property |
| <code class="prettyprint lang-xtend">average</code> |
| which will be automatically updated when |
| <code class="prettyprint lang-xtend">a</code> |
| or |
| <code class="prettyprint lang-xtend">b</code> |
| change: |
| </p> |
| |
| <pre class="prettyprint lang-java"> |
| // Java code |
| average.bind(a.add(b).divide(2)); |
| </pre> |
| |
| <p> |
| When these calculations get more sophisticated and you do a lot |
| of them the code becomes very unreadable. This is the right |
| moment to think about <a |
| href="http://www.eclipse.org/xtend/documentation.html#operators">overloaded |
| operator extensions</a> for JavaFX's |
| <code class="prettyprint lang-xtend">DoubleExpressions</code> |
| . The code to overload an operator looks like this: |
| </p> |
| |
| <pre class="prettyprint lang-xtend"> |
| def static operator_plus(DoubleExpression a, ObservableNumberValue b) { |
| a.add(b) |
| } |
| </pre> |
| |
| <p> |
| You would usually collect all such overloading methods in a |
| class |
| <code class="prettyprint lang-xtend">DoublePropertyExtensions</code> |
| and make them available using a <a |
| href="http://www.eclipse.org/xtend/documentation.html#extensionMethods">static |
| extension import</a> whenever you need them. The above Java |
| example becomes as simple as |
| </p> |
| |
| <pre class="prettyprint lang-xtend"> |
| import static extension my.company.DoublePropertyExtensions.* |
| //... |
| average << a + b / 2 |
| </pre> |
| |
| <p> |
| Extension methods and operator overloading can also be used to |
| add the missing APIs for geometry calculation, e.g. to apply a <a |
| href="http://docs.oracle.com/javafx/2/api/javafx/scene/transform/Transform.html"><code |
| class="prettyprint lang-xtend">Transform</code></a> to a <a |
| href="http://docs.oracle.com/javafx/2/api/javafx/geometry/Point3D.html"><code |
| class="prettyprint lang-xtend">Point3D</code></a> or to |
| accumulate |
| <code class="prettyprint lang-xtend">Transforms</code> |
| . For detail please see the article on <a |
| href="http://koehnlein.blogspot.de/2013/01/accumulating-javafx-transforms-with.html">"Accumulating |
| JavaFX Transforms With Xtend"</a>. |
| </p> |
| |
| <h3>Declaring Properties</h3> |
| |
| <p> |
| JavaFX properties are usually wrapped in getters and setters |
| to comply with the <a |
| href="http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html">JavaBeans</a> |
| specification. For a lazily created |
| <code class="prettyprint lang-xtend">DoubleProperty</code> |
| <code class="prettyprint lang-xtend">radius</code> |
| the <a |
| href="http://blog.netopyr.com/2011/05/19/creating-javafx-properties/">recommended |
| code</a> looks like this: |
| </p> |
| |
| <pre class="prettyprint lang-java"> |
| //Java code |
| public class Balloon { |
| private DoubleProperty radius; |
| private double _radius = 20; |
| |
| public double getRadius() { |
| return (radius != null)? radius.get() : _radius; |
| } |
| |
| public void setRadius(double value) { |
| if (radius != null) |
| radius.set(value); |
| else |
| _radius = value; |
| } |
| |
| public DoubleProperty radiusProperty() { |
| if (radius == null) |
| radius = DoubleProperty(this, "radius", _radius); |
| return radius; |
| } |
| |
| // ... |
| } |
| </pre> |
| |
| <p> |
| This is a lot of code for a simple property and a perfect use |
| case for a new language feature of Xtend: With <em>Active |
| Annotations</em> you can manipulate how Xtend is compiled to |
| Java. In our case, you could implement an <i>Active Annotation</i> |
| <code>@FXBean</code> |
| that describes the code pattern above. If an Xtend class is |
| annotated as |
| <code>@FXBean</code> |
| , this pattern is expanded for all its fields in the generated |
| Java code automatically by the compiler. So the Xtend version |
| becomes |
| </p> |
| |
| <pre class="prettyprint lang-xtend"> |
| @FXBean |
| class Balloon { |
| double radius = 20 |
| //... |
| } |
| </pre> |
| |
| <p> |
| The exemplary code for |
| <code>@FXBean</code> |
| can be found <a |
| href="https://github.com/svenefftinge/xtendfx/blob/master/xtendfx/src/xtendfx/properties/FXBean.xtend">here</a>. |
| Note that <i>Active Annotations</i> are loaded from the |
| classpath of the project at compile time, thus can reside in the |
| same workspace as the client code. They neither have to be |
| deployed to be used nor shipped with the application code. For |
| more infos on <i>Active Annotations</i> please refer to the |
| other article in the newsletter. |
| </p> |
| |
| <p> |
| I hope I could convince you that JavaFX and Xtend make a perfect |
| couple. If you want to stay up-to-date with our work on Xtend, <a |
| href="https://twitter.com/xtendlang">join us on Twitter</a> or |
| ask your questions in our <a |
| href="https://groups.google.com/forum/?fromgroups#!forum/xtend-lang">Google |
| Group</a>. |
| </p> |
| |
| <script |
| src="http://www.eclipse.org/xtend/google-code-prettify/prettify.js" |
| type="text/javascript"></script> |
| <script |
| src="http://www.eclipse.org/xtend/google-code-prettify/lang-xtend.js" |
| type="text/javascript"></script> |
| <script type="text/javascript"> |
| prettyPrint(); |
| </script> |
| |
| <div class="bottomitem"> |
| <h3>About the Authors</h3> |
| |
| <div class="row"> |
| <div class="col-sm-12"> |
| <div class="row"> |
| <div class="col-sm-8"> |
| <img class="author-picture" |
| src="/community/eclipse_newsletter/2013/march/images/jan_koehnlein1.jpg" |
| alt="Jan Koehnlein" /> |
| </div> |
| <div class="col-sm-16"> |
| <p class="author-name"> |
| Jan Koehnlein <br /> |
| <a href="http://www.itemis.com/">itemis</a> |
| </p> |
| <ul class="author-link"> |
| <li><a href="http://koehnlein.blogspot.ca/">Blog</a></li> |
| <li><a href="https://twitter.com/jankoehnlein">Twitter</a></li> |
| <li><a href="https://plus.google.com/116635061773096754601">Google+</a></li> |
| <li><a href="<?php echo $original_url; ?>">Original Article</a></li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |