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.

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 and ListValueFactory in JavaFX

The TableView control is pretty complete to use and very convenient. But the classical use of it specify that a line is represented by an instance of an Object, usually a property bean. But in some cases it would be very useful to have a line composed by multiple instances of a specific class, i.e. having an instance per column, and each column should display a particular property of your instance. A concrete example would be the management interface of translations in NetBeans. Indeed, this screen display all properties files of a particular resource bundle, having a column for the translations keys and as many columns as needed to display the translations for each keys.

netbeans_i18n_editor

As said above, we could need an instance of object per column, meaning multiple instances per line. So a line of the TableView should be a List<? extends Object>. The problem is to know which data to display in a particular column.

ListValueFactory

As you may know, you can set CellValueFactory on a TableColumn, which will display the value in the cell. For example, you can set a PropertyValueFactory that will look for a property of a bean, and will display it. But that works if you have a single Object per line, not a collection. So we will create our own implementation that will check a property of a bean inside a list.

public class ListValueFactory<T, V> implements Callback<TableColumn.CellDataFeatures<List<T>, V>, ObservableValue<V>> {
  
  private String propertyName;

  public ListValueFactory(String propertyName) {
    this.propertyName = propertyName;
  }
    
  @Override
  public ObservableValue<V> call(TableColumn.CellDataFeatures<List<T> , V> p) {
        
    int index = 0;
        
    ListIterator<TableColumn<List<T>, ?>> iterator = 
       p.getTableView().getColumns().listIterator();
        
    TableColumn tmpColumn;
    while(iterator.hasNext()) {
      tmpColumn = iterator.next();

      if(tmpColumn == p.getTableColumn())
        break;
      else
        index++;
    }

    T object = p.getValue().get(index);

    try {
      Method method = object.getClass().getMethod(propertyName.concat("Property"));
      return (Property<V>) method.invoke(object);
    } catch (Exception ex) {
      Logger.getLogger(ListValueFactory.class.getName()).log(Level.SEVERE, null, ex);
      return null;
    }
  }
}

As you can see, the implementation is totally generic. First, we try to know the index of the column and we suppose that this index is the same index of the data in the list of data. WARNING: this is totally wrong if, in your UI, you move columns ; so take this into consideration because the implementation is not shown here. Once we have the index, we look for the data in the list, and finally, using so introspection, we look for the getter of the property in order to get the value. And that’s it.

Usage

To use this implementation in your code, you juste have to do the following:

TableView<List<Person>> tableView = new TableView<>();
TableColumn<String> columnOne = new TableColumn<>("First name one");
columnOne.setCellValueFactory(new ListValueFactory<List<Person>, String>("firstName"));
TableColumn<String> columnTwo = new TableColumn<>("First name two");
columnTwo.setCellValueFactory(new ListValueFactory<List<Person>, String>("firstName"));
tableView.getColumns().addAll(columnOne, columnTwo);

“Bind” components’ size to a MediaView’s size in JavaFX

The MediaView is a control allowing you to add videos and sounds to your JavaFX application. If you are playing a video, maybe you would like another control to have the same size. For example, you can have a video played next to an image that you would like to have the same height. The easy thing would like to do some property binding like this:

final MediaView mediaView = new MediaView(aPlayerInstance);
mediaView.setFitWidth(200);

final ImageView imageView = new ImageView(anImageInstance);
imageView.fitHeightProperty().bind(mediaView.heightProperty());

But this code is wrong because the MediaView doesn’t have a height property. So in order to succeed in our goal, the MediaView has a boundsInLocalProperty which can be used to change the size of the ImageView in our case. Look at this code example:

final MediaView mediaView = new MediaView(aPlayerInstance);
mediaView.setFitWidth(200);

final ImageView imageView = new ImageView(anImageInstance);

mediaView.boundsInLocalProperty().addListener(new ChangeListener<Bounds>() {
  @Override
  public void changed(ObservableValue<? extends Bounds> observableValue, Bounds bounds, Bounds bounds2) {
    imageView.setFitHeight(bounds2.getHeight());
  }
});

Of course you have to do some nullity checks to make your code more robust.

Build JavaFX runnable JAR with IntelliJ IDEA (and Ant)

For years now I’ve been using NetBeans and I’m satisfied about it. But I wanted to give IntelliJ IDEA a try so I decided to test it by creating some JavaFX apps. And if you’re following the news, JetBeains has released IntelliJ IDEA 12. The thing is IntelliJ doesn’t have specific JavaFX features so I really wanted to see how to deal with it. Since JavaFX 2 is a part of the JDK 7 now, you won’t face any problem according like the JavaFX classes. The “problem” is I really have my habits on NetBeans and it is kind of difficult to throw them away. And one of my first problem was: how do I create a runnable JAR for my JavaFX app? Well I know the stuff about Ant tasks, the JavaFX packager in theory. But I didn’t had to really know them in details because NetBeans really does everything for you.
To be very clear: I won’t judge neither NetBeans, neither IntelliJ. Both have their pros and cons and both are great products. The subject here is really to focus on how to create a runnable JavaFX JAR in IntelliJ using Ant. And because I am really a newbie to IntelliJ, I hope this post could help others.

Configuration and tools

The configuration and tools that is used:

  • OS X Lion or Mountain Lion
  • Java 7u9 (with JavaFX 2.2.3)
  • IntelliJ IDEA 12 CE
  • Ant (shipped with the IDE)

The project I’m using is a simple project that you can grab here.

The Ant build script

First thing we have to do is to create the Ant build script. Go to Build > Generate Ant Build …
IntelliJ_Generate_Ant_build_script_01
Then create the script by giving it a name. I personally decided to make it as simple as possible.
IntelliJ_Generate_Ant_build_script_02
After that, I replaced the whole generated content of the build script by the following one:

<?xml version="1.0" encoding="UTF-8"?>
<project name="testerfx" default="default" basedir="." xmlns:fx="javafx:com.sun.javafx.tools.ant">

  <property name="java.home" value="/Library/Java/JavaVirtualMachines/jdk1.7.0_09.jdk/Contents/Home"/>
  <property name="source.dir" value="src"/>
  <property name="out.dir" value="build"/>
  <property name="out.dir.classes" value="${out.dir}/classes" />
  <property name="out.dir.dist" value="${out.dir}/dist"/>
  <property name="app.jar.name" value="TesterFX.jar"/>

  <path id="classpath">
    <fileset dir="${java.home}/lib" includes="**/*.jar"/>
  </path>

  <target name="default">
    <taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
                 uri="javafx:com.sun.javafx.tools.ant"
                 classpath=".:${java.home}/lib/ant-javafx.jar"/>
  </target>

  <target name="clean">
    <delete dir="${out.dir}"/>
  </target>

  <target name="init" depends="clean">
    <mkdir dir="${out.dir}"/>
    <mkdir dir="${out.dir.classes}"/>
    <mkdir dir="${out.dir.dist}"/>
  </target>

  <target name="compile" depends="default, init">
    <javac srcdir="${source.dir}" destdir="${out.dir}/classes" classpathref="classpath"
               source="1.7"
               target="1.7" />
    <copy todir="${out.dir}/classes">
      <fileset dir="${source.dir}">
        <include name="**/*.png" />
        <include name="**/*.fxml" />
        <include name="**/*.css" />
      </fileset>
    </copy>
  </target>

  <target name="build" depends="compile">
    <fx:application id="TesterFX" mainClass="com.twasyl.testerfx.app.TesterFX"/>
    <fx:jar destfile="${out.dir.dist}/${app.jar.name}">
      <fx:application refid="TesterFX"/>

      <manifest>
        <attribute name="Implementation-Vendor"
                           value="Thierry"/>
        <attribute name="Implementation-Title"
                           value="TesterFX"/>
        <attribute name="Implementation-Version" value="1.0"/>
      </manifest>

      <fileset dir="${out.dir.classes}"/>
    </fx:jar>
  </target>
</project>

If you’re familiar with Ant, this is pretty easy: I define some basic targets for cleaning and compiling. The most interesting part is the target build. It is there that the final jar for our application is done using some new tags like:

  • fx:application that represents our JavaFX app, where you define the application class, the fallback one and so on ;
  • fx:jar that will create the final JAR by assembling the classes, convert CSS files into binary format if wanted and so son.

Of course there are other tags like fx:deploy, fx:signJar, etc. But here we only wanted to build a simple JAR without any particular configuration.

Try it

Once your build script is ready you just have to execute the build target to get your runnable JAR. To do so, at the right of IntelliJ click on Ant Build and then on the + in order to add your build script.IntelliJ_Generate_Ant_build_script_03
Choose your file:
IntelliJ_Generate_Ant_build_script_04
And then you will be able to execute targets you want.
IntelliJ_Generate_Ant_build_script_05

That’s it. I hope this could help you.

Useful resources

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.

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.