TextFlow with JavaFX 2

When ever you want to display a large portion of text in your application the Text node is your friend. Text allows you to define a wrapping width and thereby allows nice multyline text without letting you bother about the line break.

However what when your text is not that simple? It might contain portions that are differently formatted? Links? Or even icons?

JavaFX 8 has a solution for this: TextFlow. If you are however stuck with JavaFX 2 for whatever reason, there is simple workaround: pack all the Nodes into a FlowPane and define the wrapping width to be the preferred width.

public class DecoratedText extends FlowPane {

    private IntegerProperty wrappingWidth;
    private ReadOnlyObjectProperty<Font> font;
    public DecoratedText(Font font) {
        super(Orientation.HORIZONTAL);
        wrappingWidth = new SimpleIntegerProperty(this, "wrappingWidth", 0);
        getStylesheets().add(getClass().getResource(getClass().getSimpleName()+".css").toExternalForm());
        this.font = new SimpleObjectProperty<>(this, "font", font);
        prefWidthProperty().bindBidirectional(wrappingWidth);
    }

    /**
     * Append text. If the text represents a paragraph (indicated by '\n'), it
     * is not broken up into its parts.
     * @param text
     */
    public void append(String text) {
        if (text.endsWith("\n")) {
            Text decoText = new Text(text);
            //decoText.getStyleClass().add("decoratedText-text");
            decoText.setFont(font.get());
            decoText.wrappingWidthProperty().bind(wrappingWidth);
            getChildren().add(decoText);
        } else {
            String[] parts = text.split(" ");
            for (String part : parts) {
                Text decoText = new Text(part+" ");
                //decoText.getStyleClass().add("decoratedText-text");
                decoText.setFont(font.get());
                getChildren().add(decoText);
            }
        }
    }

    /**
     * Append a control.
     * @param control
     */
    public void append(Node control) {
         getChildren().add(control);
    }

    public int getWrappingWidth() {
        return wrappingWidth.get();
    }

    public IntegerProperty wrappingWidthProperty() {
        return wrappingWidth;
    }

    public void setWrappingWidth(int wrappingWidth) {
        this.wrappingWidth.set(wrappingWidth);
    }
}

The idea here is to leave text blocks which represent a paragraph by themselves as Text node. However if the paragraph contains some other node, it is splitt up into words. Thereby delegating the wrapping functionality to the underlying FlowPane.

While this solution here is not particularly sophisticated, it suffices my needs. Nevertheless I will replace it with TextFlow as soon as I migrate to Java 8.

ServletFilter with Spring Dependency Injection

Recently I stumbled upon the task to implement a ServletFilter in our Spring MVC web application. The filter should use one of the services we defined as bean, so it was natural to find a way to implement a servletFilter as a Spring bean so DI can be leveraged.

I got lucky, as I stumbled on this post in German, detailing what has to be done. Basically there are three things to do:

  1. Implement the filter (implementing the javax.servlet.Filter interface)
  2. Define it as a Spring bean either through annotation, XML or Java configuration
  3. Use org.springframework.web.filter.DelegatingFilterProxy as the filter class in your web.xml. The filter-name must match the name of your bean.

If your filter implements an init or destroy method, which actually do something, you also have to specify the init-param targetFilterLifecycle with the value true, to force the proxy to call these methods on the underlying bean.

<init-param>
 <param-name>targetFilterLifecycle</param-name>
 <param-value>true</param-value>
</init-param>

That's it.

JavaFX layout anf hover

I run into an issue that might be obvious to some… Never the less here it is.

I created a scene with a background image, labels, which have a PerspectiveTransformation applied to them, and Polygon shapes over the transformed labels, so I can have hover over the polygons and simulate an action of the label. Everything looked fine. However I never hovered over one of the polygons. I then added another polygon in the middle to the root StackPane. There happened the most curious thing: I only could hover over it when I moved in from the left side. This got me thinking, that there is probably some component on top, which has a transparent part there. Adding the polygon as the very last component confirmed this assumption. So add your components to the stack in the correct back to front order to avoid issues like this.

Using Groovy to update KPhotoAlbum database

Since some time now KPhotoAlbum crashes on my Linux Mint Debian Edition, when new images are searched (and some other actions). As this is really annoying I looked for solutions. Updating to a newer version than 4.1.1 was not possible. Compiling from source was also out due to library version conflicts. All I really needed was a way to add new files to the index.xml file, which is KPhotoAlbums database. Due to the XML nature of the problem, I gave Groovy a shot.

„Using Groovy to update KPhotoAlbum database“ weiterlesen

Cannot locate spring namespace

When starting my OpenPatrician application from within Eclipse everything worked fine. But when using the assembly everything fell apart. The reason for this is simple, once figured out. I am creating an assembly of all the modules and their dependencies. Should it happen, that different dependencies provide the same resource, say like a manifest file, the first file will end up in the final jar file.

The different spring dependencies define several configurations which I had only part of in the final jar file. These are the files located in META-INF of the spring-…jar files:

  • spring.factories
  • spring.handlers
  • spring.tools
  • spring.schemas

Now all you have to do is, merge the contents into one file and make sure that is the file that ends up in the final jar file.

To do this I created an additional MetaData module, which is the first dependency in the assembly maven project. That way the files from the MetaData module get picked up.

See also http://blog.idm.fr/2009/09/maven-assembly-plugin-and-spring-namespace-handlers.html