Partial HTML generation from textile using eclipse Mylyn standalone

The title is pretty much explicit. For SlideshowFX, I needed to generate HTML content from textile, in order to define slide’s content. Looking for a lib, I found eclipse Mylyn that can be used in a standalone way. The library is pretty powerful but I have to look a lot at the sources in order to get the things done how I wanted to (#LukeAtTheSource power). Generally to convert a markup string into a HTML one, you create a MarkupLanguage as well as a MarkupParser and do the following:

final MarkupLanguage language = new TextileLanguage();
final MarkupParser parser = new MarkupParser(language);
parser.parseToHTML("h1. My little String");

The thing is that this code will create a whole HTML document (with html, head, body and so on tags). Me needs were to just get the HTML code corresponding to my string, e.g.

<h1>My little String</h1>

So the code should be changed to use a DocumentBuilder, like the following one:

final StringWriter writer = new StringWriter();
final DocumentBuilder builder = new HtmlDocumentBuilder(writer);
final MarkupLanguage language = new TextileLanguage();
final MarkupParser parser = new MarkupParser(language, builder);

// false indicates to not produce a whole HTML document
parser.parse("h1. My little String", false);

writer.flush();
writer.close();

String htmlContent = writer.toString();

This is almost done except that Mylyn generates IDs (which is kind of normal right?) by using the content of the markup. In short, I wanted to avoid IDs’ generation but I could’t find a right and efficient way to do it. So I decided to ensure uniqueness of IDs by always getting the current timestamp. Maybe it’s not a wonderful solution, but for the purpose of this little tutorial it will be perfect. The main idea is to change the ID generation and for doing this, you have to override some classes, because the default ID generation strategy is stored as a static and final variable, and no setters are available. The following example demonstrates how to do it:

final StringWriter writer = new StringWriter();

// The generation strategy generates IDs using the current timestamp
final IdGenerationStrategy idGenerationStrategy = new IdGenerationStrategy() {
  @Override
  public String generateId(String s) {
    return System.currentTimeMillis() + "";
  }
};

final IdGenerator idGenerator = new IdGenerator();
idGenerator.setGenerationStrategy(idGenerationStrategy);

final TextileContentState contentState = new TextileContentState() {
  @Override
  public IdGenerator getIdGenerator() {
    return idGenerator;
  }
};

// Override the language to return the created contentState used for the ID generation
final MarkupLanguage language = new TextileLanguage() {
  @Override
  protected ContentState createState() {
    return contentState;
  }
};

final DocumentBuilder builder = new HtmlDocumentBuilder(writer);

final MarkupParser parser = new MarkupParser(language, builder);

parser.parse(markupString, false);

writer.flush();
writer.close();

final String htmlContent = writer.toString();

This is it. Enjoy.

Update your Scene in JavaFX

Usually it is very simple to update your scene in JavaFX. For example if you want to update the X and Y position of your nodes, you can often simply do some stuff like:

node.setLayoutX(100d);
node.setLayoutY(150d);

But this isn’t a good way of doing it. In JavaFX you have to be sure you are in the JavaFX application thread. But how can you know this?

Platform.isApplicationFxThread();

But what if you’re not in that thread?

Platform.runLater(Runnable r);

So each time you would like to update your scene manually, you should check if you’re or not in the FX application thread. So let’s make a really simple helper class:

/**
 * @author Thierry Wasylczenko
 */
public class PlatformHelper {

    public static void run(Runnable treatment) {
        if(treatment == null) throw new IllegalArgumentException("The treatment to perform can not be null");

        if(Platform.isFxApplicationThread()) treatment.run();
        else Platform.runLater(treatment);
    }
}

The method run does the check for you. Finally you can use a lambda expression to execute that code:

final Node node = ... ;
PlatformHelper.run(() -> {
  node.setLayoutX(100d);
  node.setLayoutY(150d);
});

That’s it.

PathTextField: quick example of property usage in JavaFX

Context

Properties and binding in JavaFX is a really interesting feature that sometimes is hard to illustrate. Recently I just faced a problem in CompilerFX: file paths entered by the user could be problematic. Indeed on some platforms path separator is \ and on others it is /. In Java you can often use / as path separator.

Practice

So in our example, you can choose many solutions like for example:

  • When the user submit the path in a text field, replace all \ by /;
  • When the user enter a \, use a key event to replace it;
  • Choose a more JavaFX way.

Let’s deal with the third solution. Have this ones in mind:

  • In JavaFX you have the properties, allowing you to listen for a change using a ChangeListener;
  • The text of a TextField is store in the text property.

You could implement the second solution listen previously but let’s work with a custom text field that will replace replace all \ by /.

public class PathTextField extends TextField {

  {
    textProperty().addListener(new ChangeListener<String>() {
      @Override
      public void changed(ObservableValue<? extends String> observableValue, String s, String s2) {
        if(!textProperty().isBound() && s2 != null) {
          textProperty().set(s2.replaceAll("\\\\", "/"));
        }
      }
    });
  }
}

In this component, we place a ChangeListener on the text property in order to replace all \ by /. Then you can use it in your FXML files for example.

TableView: column’s width using percentage in JavaFX

In my previous post you’ve successfully learned how to simply use a TableView. It is obvious that a tables has columns and columns have a size. Sometimes you would like to specify the width of your columns using a percentage. Unfortunately it’s not a native feature of JavaFX 2. Well this ain’t a problem because, again, it is very simple to implement it yourself by creating a custom control.

PTableColumn

Creating a custom control in our case is very simple because what we need to do it basically already done. Indeed what we need is to know the size of our table and then compute our column’s width according a given percentage. All others behaviours are already managed by the TableColumn class. So we will create a class named PTableColumn (‘P’ standing obviously for percentage) and which extends the TableColumn class.

public class PTableColumn<S, T> extends javafx.scene.control.TableColumn<S, T> {

  private final DoubleProperty percentageWidth = new SimpleDoubleProperty(1);

  public PTableColumn() {
    tableViewProperty().addListener(new ChangeListener<TableView<S>>() {

      @Override
      public void changed(ObservableValue<? extends TableView<S>> ov, TableView<S> t, TableView<S> t1) {
        if(PTableColumn.this.prefWidthProperty().isBound()) {
          PTableColumn.this.prefWidthProperty().unbind();
        }

        PTableColumn.this.prefWidthProperty().bind(t1.widthProperty().multiply(percentageWidth));
      }
    });
  }
    
  public final DoubleProperty percentageWidthProperty() {
    return this.percentageWidth;
  }
    
  public final double getPercentageWidth() {
    return this.percentageWidthProperty().get();
  }
    
  public final void setPercentageWidth(double value) throws IllegalArgumentException {
    if(value >= 0 && value <= 1) {
      this.percentageWidthProperty().set(value);
    } else {
      throw new IllegalArgumentException(String.format("The provided percentage width is not between 0.0 and 1.0. Value is: %1$s", value));
    }
  }
}

As you can notice, we add a listener to the TableView property of the TableColumn. So each time the table changes, you just update the column’s width. The prefWidthProperty is bound to our percentageWidthPropery using a NumberBinding. So each time our property changes, the width is recalculated.

Use it

Now the only thing left to do is use our custom column in our FXML. Don’t forget to import it!

<!-- ... -->
<?import com.twasyl.envviewer.controls.*?>
<!-- ... -->
<TableView fx:id="propertiesTable">
  <columns>
    <PTableColumn text="Type" fx:id="typeColumn" percentageWidth="0.08">
      <!-- ... -->
    </PTableColumn>
    <!-- ... -->
  </columns>
</TableView>

Well as I said, really easy.

The source code is available here.

TableView: display tables in JavaFX

If you were used to use JTable in Swing in order to display tables in your UI, you probably know that was kind of difficult to use and customise. In JavaFX you have what is called a TableView which is complex component allowing you to do a lot of stuff. In this post we will try to cover some basics about the TableView.

Main classes

In order to display tables in JavaFX you will use a TableView. The TableView will host TableColumns. That are the two main classes you will use in order to create a table. The TableRow class also exists but you won’t use it much, except if you want to create your own rowFactory. But that is a bit out of the scope of this post.

Bring up some Generics

A table is a container that will host some kind of data: a product, an account, an item, etc. So your TableView will host some kind of data. So the following declaration makes sense:

TableView<Property> propertiesTable = new ...

Columns will host a specific value of an item in the table, like the name of the product for example. And the name is a string. So declaring columns will be like this:

TableColumn<Property, String> nameColumn;
TableColumn<Property, String> valueColumn;

The power of properties

One of the great concept of JavaFX 2 is the properties and binding (read about here). And it is very useful in our case. Indeed we know what to display in our table, we have the data but I don’t want to say each time I need a new entry in my table that the name is in the first column, the value in the second, and so on. So let’s have a look. First of all I’m going to create a JavaBean with properties:

public class Property implements Serializable {
  public enum Type {
    SYSTEM, ENVIRONMENT
  }

  private final StringProperty name = new SimpleStringProperty();
  private final StringProperty value = new SimpleStringProperty();
  private final ObjectProperty<Type> type = new SimpleObjectProperty<>();
    
  public Property() {
  }
    
  public Property(String name, String value, Type type) {
    this.name.set(name);
    this.value.set(value);
    this.type.set(type);
  }
    
  public final StringProperty nameProperty() {
    return this.name;
  }
    
  public final String getName() {
    return this.nameProperty().get();
  }
    
  public final void setName(String name) {
    this.nameProperty().set(name);
  }
    
  public final StringProperty valueProperty() {
    return this.value;
  }
    
  public final String getValue() {
    return this.valueProperty().get();
  }
    
  public final void setValue(String value) {
    this.valueProperty().set(value);
  }
    
  public final ObjectProperty<Type> typeProperty() {
    return this.type;
  }
    
  public final Type getType() {
    return this.typeProperty().get();
  }

  public final void setType(Type type) {
    this.typeProperty().set(type);
  }
}

This quite simple. But now the real power will be revealed. We will create our table completely in FXML, without anything else. But you can of course create your table completely using pure Java code (just have a look on the Oracle website).

<BorderPane prefHeight="800" prefWidth="1000" fx:id="rootPane"
    xmlns:fx="http://javafx.com/fxml"
    fx:controller="com.twasyl.envviewer.controllers.EnvViewerController">
  <center>
    <TableView fx:id="propertiesTable">
      <columns>
        <TableColumn text="Type" fx:id="typeColumn">
          <cellValueFactory>
            <PropertyValueFactory property="type" />
          </cellValueFactory>
        </TableColumn>
        <TableColumn text="Name" fx:id="nameColumn">
          <cellValueFactory>
            <PropertyValueFactory property="name" />
          </cellValueFactory>
        </TableColumn>
        <TableColumn text="Value" fx:id="valueColumn">
          <cellValueFactory>
            <PropertyValueFactory property="value" />
          </cellValueFactory>
        </TableColumn>
      </columns>
    </TableView>
  </center>
</BorderPane>

And now take a look at the controller:

public class EnvViewerController implements Initializable {
    
  @FXML
  private Pane rootPane;
  @FXML
  private TableView<Property> propertiesTable;
  @FXML
  private TableColumn<Property, String> nameColumn;
  @FXML
  private TableColumn<Property, String> valueColumn;
  @FXML
  private TableColumn<Property, Type> typeColumn;
    
  @Override
  public void initialize(URL url, ResourceBundle rb) {
  }
}

As you can read, each TableColumn tag has a cellValueFactory one, which have a PropertyValueFactory. And this last one has an attribute named property. So what about everything? That simply means the column is bound to a property of the main content of the table. In other words, our table contains some Property objects (our JavaBean class) and the first column is bound to the type property, the second to the name one and the third to the value. Easy right? Here is a little screenshot:
Empty EnvViewer
Now we will modify our controller class in order to add some items to our table:

@Override
public void initialize(URL url, ResourceBundle rb) {
        
  for(Map.Entry entry : System.getProperties().entrySet()) {
    propertiesTable.getItems().add(new Property(entry.getKey().toString(), entry.getValue().toString(), Type.SYSTEM));
  }
        
  for(Map.Entry entry : System.getenv().entrySet()) {
    propertiesTable.getItems().add(new Property(entry.getKey().toString(), entry.getValue().toString(), Type.ENVIRONMENT));
  }
}

And this is what you get:
EnvViewer filled
And the TableView comes with nice features like having sortable columns by default, you can move columns, and so on. These features were long to develop in Swing so JavaFX brings some really nice feature natively.

Of course you can do a lot more with TableViews, like editing the data, respond to user’s clicks, dynamically add data, customise the look & feel and so on. Maybe I’ll blog about some other features.

The code is from a little app I’ve done and that I’ll update to provide new features. You can find it here.

PS: this blog post took me much more time to write than coding the app, just saying!

Keyboard shortcuts and mnemonic in JavaFX

Nowadays you won’t find an application without keyboard shortcuts and mnemonic, that’s a fact. This article is about to deal with them in a menu in a JavaFX 2 application. The way to do it is very simple and powerful.

Set up a context

In order to introduce you the concepts, let’s set up the context I use in TweetWallFX.

FXML menubar

I have an FXML that contains my application menubar which is the following one:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<MenuBar id="menuBar" fx:id="menuBar" xmlns:fx="http://javafx.com/fxml" fx:controller="com.twasyl.tweetwallfx.controllers.MenuController">
  <menus>
    <Menu text="File" mnemonicParsing="true">
      <items>
        <MenuItem fx:id="accountMenuItem" text="Account ..." onAction="#displayAccount" />
      </items>
    </Menu>
    <Menu text="View">
      <items>
        <MenuItem fx:id="fullScreenMenuItem" text="Fullscreen" onAction="#displayFullscreen" />
      </items>
    </Menu>
    <Menu text="_Tools" mnemonicParsing="true">
      <items>
        <MenuItem fx:id="musicPlayerMenuItem" text="Music player" onAction="#playBackgroundSongAction" />
      </items>
    </Menu>
  </menus>
</MenuBar>

Controller

And the needed code for the controller:

public class MenuController implements Initializable {
  @FXML private MenuBar menuBar;
  @FXML private MenuItem fullScreenMenuItem;
  @FXML private MenuItem musicPlayerMenuItem;
  @FXML private MenuItem accountMenuItem;

  @Override
  public void initialize(URL url, ResourceBundle rb) {
    // TODO create the keyboard shortcuts here
  }
}

Mnemonics

The easy one is the mnemonic because you don’t need to write a lot of stuff … ! The mnemonic, on Windows, is when underscored letter of a menu of a menubar. When you press Alt+<the letter> the menu will be opened. It gives you a quick access to the menu. In order to define a mnemonic, in the text of your menu, place the character ‘_’ and set the mnemonicParsingProperty() to true either in your FXML or either in your backing code. And automatically, JavaFX will compute and set the mnemonic for your menu. That’s it! Easy, isn’t it?

Keyboard shortcut

Defining a keyboard shortcut for a menu entry isn’t really though when you know where to look at. In JavafX, it’s called an accelerator. An accelerator is composed of a combination of keys:

  • a main key: A, B, C, …
  • a modifier: Ctrl, Meta, Shift, Alt

. In order to define an accelerator, there are, for me, two main classes:

  • KeyCombination
  • KeyCode

Once you got them defining an accelerator is easy because it is a … KeyCombination. A keyboard shortcut is usually something like Ctrl+<a key> on Windows and Meta+<a key> on Mac, which is called the modifier. The first thing is to manage both system in order to know which modifier (Ctrl or Meta) to use … JavaFX already manages this for you by providing KeyCombination.SHORTCUT_ANY and KeyCombination.SHORTCUT_DOWN. So use them instead of CTRL or META if you want to be platform independent.
So if I want to create a combination for (Ctrl | Meta) + F as accelerator of a menu item I can use this piece of code:

this.fullScreenMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.F, KeyCombination.CONTROL_DOWN, KeyCombination.SHORTCUT_DOWN));

Nothing more, nothing less. Of course you can combine multiple modifiers like Shortcut and Shift for example to get Shortcut+Shift+F.

Properties and Bindings in JavaFX

JavaFX 2 brings the Properties and Bindings concepts. I will do a little overview of the possibilities offered by this two mechanisms and give you a quick example of how you can use them while building a JavaFX UI.

Properties

Properties allow you to expand and improve the well known JavaBean concept. Indeed it brings you a way to “observe” a value of bean and to have a full event delivery system. That means you will be able to perform an action when the value changes. Let’s see a simple bean:

public class Rectangle {

  private double width;
  private double height;
  private double surface;

  public double getWidth() { return this.width; }
  public void setWidth(double width) { this.width = width; } 
  public double getHeight() { return this.height; }
  public double setHeight(double height) { this.height = height; }
  public double getSurface() {
    this.surface = this.getWidth() * this.getHeight();
    return this.surface;
  }
}

Now we’re going to just create a main that will be used to display the values of a rectangle.

public class Runner {
  public static void main(String ... args) {
    Rectangle rect = new Rectangle() {{
      setWidth(100);
      setHeight(200);
    }};

    System.out.println("WIDTH: " + rect.getWidth());
    System.out.println("HEIGHT: " + rect.getHeight());
    System.out.println("SURFACE: " + rect.getSurface());
  }
}

In order to transform this bean to use Properties, you will replace the type of each field by the corresponding type in Properties. For example (there are more …):

Type Proerties type
int IntegerProperty
double DoubleProperty
short ShortProperty
String StringProperty
Object ObjectProperty<T>

You also have to respect some conventions like:

  • having public final getter/setter for each field
  • having public getter for the property

Let’s make the changes to our bean:

public class Rectangle {

  private DoubleProperty width;
  private DoubleProperty height;
  private DoubleProperty surface;

  public DoubleProperty widthProperty() {
    if(this.width == null) { this.width = new SimpleDoubleProperty(); }
    return this.width;
  }
  public final double getWidth() { return this.widthProperty().get(); }
  public final void setWidth(double width) { this.widthProperty().set(width); }

  public DoubleProperty heightProperty() {
    if(this.height == null) { this.height = new SimpleDoubleProperty(); }
    return this.height;
  }
  public final double getHeight() { return this.heightProperty().get(); }
  public final void setHeight(double height) { this.heightProperty().set(height); }

  public DoubleProperty surfaceProperty() {
    if(this.surface == null) { this.surface = new SimpleDoubleProperty(); }
    return this.surface;
  }
  public final double getSurface() {
    this.surfaceProperty().set(this.getWidth() * this.getHeight());
    return this.surfaceProperty().get();
  }
}

As you can see, the getters for the properties don’t match classic convention we’ve known for a JavaBean. Indeed the name of the getter is always like: <fieldName>Property.

Properties and events

Like I said you can “listen” for changes on a property. It may be useful to update a part of your software, tracing a log, etc. In order to do this you can choose to add a listener to a property. Listeners can be of two types:

  • ChangeListener: to quickly explain it, you have old and new value of the property
  • InvalidationListener: to quickly explain it, you just know the value was changed

So for example, let’s add a listener to the surface property:

// ...
public DoubleProperty surfaceProperty() {
  if(this.surface == null) {
    this.surface = new SimpleDoubleProperty();
    this.surface.addListener(new ChangeListener<Number>() {
      @Override
      public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
        System.out.println("The value was changed from " + oldValue.toString() + " to " + newValue.toString());
      }
    });
  }
  return this.surface;
}
// ...

Now each time the value changes, the message will be displayed.

Bindings

The rectangle example with the surface wasn’t chosen for nothing. Indeed it will serves as demonstration of the Bindings concept of JavaFX. The surface is always the width multiplied by the height. In our example we made the update of the surface manually but we don’t need to, thanks to the Bindings API. You have three major bindings:

  • Unidirectional binding
  • Bidirectional binding
  • Number binding

Unidirectional binding

You can bind a property p1 to another p2, meaning when p2 is modified, p1 will be updated with the new value of p2.

// Useful for a square
this.widthProperty().bind(this.heightProperty());

Bidirectional binding

You can bin two properties one to each other meaning when one is updated, the other will be too.

this.widthProperty().bindBidirectional(this.heightProperty());

Number binding

In our example, the surface should be updated if the width and/or height is updated, and the surface is the multiplication of the width and height. We will use a number binding.

NumberBinding multiplication = Bindings.multiply(this.widthProperty(), this.heightProperty());
this.surfaceProperty().bind(multiplication);

The number binding will be updated each time the width and/or height is updated, and because we bind the surface property to it, the surface will be updated as well. You can update the surfaceProperty() method by this:

public DoubleProperty surfaceProperty() {
  if(this.surface == null) {
    this.surface = new SimpleDoubleProperty();
    this.surface.addListener(new ChangeListener() {
      @Override
      public void changed(ObservableValue observable, Number oldValue, Number newValue) {
        System.out.println("The value was changed from " + oldValue.toString() + " to " + newValue.toString());
      }
    });
    this.surface.bind(Bindings.multiply(this.widthProperty(), this.heightProperty()));
  }
  return this.surface;
}

public final double getSurface() {
  return this.surfaceProperty().get();
}

Using Properties and Bindings in a UI

Do you remember the old times, when we were building some Swing UI? When the app was resized, you had to compute the new size of the components. Now things have changed, in a much better way with JavaFX! Indeed, every component in JFX is built using Properties: widthProperty(), heightProperty(), visibleProperty(), layoutXProperty(), layoutYProperty(), styleProperty(), etc etc etc.
So if you need to update the size of a particular component which depends on the size of another one, no problem ! You can bind properties using NumberBinding if you want to do a ratio for example, or (bi | uni)directional binding.
The concept is very powerful and should remember you the Observer/Observable pattern we use to have in JSE.

This was a quick overview of Properties and Bindings, now it’s time for you to code.