Mar 04

FontAwesomeFX 8.2 released

I made some refactorings and have now released FontAwesomeFX 8.2 containing some (more or less) minor changes:

  • Icon enums renamed: ‘*Name’ is now ‘*Icons’ (e.g. ‘FontAwesomeIcons’ instead of ‘FontAwesomeIconName’)
  • added a ‘BLANK’ icon to both FontAwesomeIcons and WeatherIcons which is in fact unicode ‘\u0020′ (SPACE) (@dlemmermann! ;-))
  • GlyphsBuilder: icon(GlyphIconName glyphIconName) is now glyph(GlyphIcons glyph)
  • removed unnecessary code
  • FXML:
    • ‘iconName’ is now ‘glyphName’
    • ‘glyphStyleClass’ is now ‘styleClass': no extra GlyphStyle class just assign the class via Section “JavaFX CSS” -> Style Class.

So if you have already used FontAwesomeFX 8.1 you will also have to adjust your code, sorry for the inconvenience but I think now its a more reasonable wording for future releases!

Some FXML Examples:
2015-03-04 12_49_16-FontAwesomeFX - NetBeans IDE 8.0.2
SceneBuilder:
2015-03-04 12_44_15-glyphs_fxml_demo.fxml
2015-03-04 12_46_09-glyphs_fxml_demo.fxml

2015-03-04 12_49_25-FontAwesomeFX - NetBeans IDE 8.0.2
SceneBuilder:
2015-03-04 12_47_13-glyphs_fxml_demo.fxml
2015-03-04 12_47_25-glyphs_fxml_demo.fxml
2015-03-04 12_45_56-glyphs_fxml_demo.fxml

Hint:
I planned to make the Icon choice in SceneBuilder more comfortable. I wanted to provide a drop-down instead of need to look up the right name and to put it into the TextField. But unfortunately by now I didn’t make it to get SceneBuilder to work with the Glyphs-choice as enum. It worked very well with just one GlyphIcon on the pane but when a 2nd one is placed SB crashed. But I will continue to try to find out what went wrong – stay tuned.

Get 8.2:
Download Binaries: Download
Sources available at Bitbucket

Maven:

<dependency>
  <groupId>de.jensd</groupId>
  <artifactId>fontawesomefx</artifactId>
  <version>8.2</version>
</dependency>
Feb 23

MQTT.fx 0.0.14.3 – bug fix release

You can download latest binaries at mqttfx.org.
Bugs and feature requests can be reported via the issue tracker.

Version 0.0.14.3 contains some bug fixes (since 0.0.14 release):

  • [Fixed] Issue #27 Disconnection when publishing to a second broker
  • [Fixed] bug when to show only latest messages
  • [Fixed] bug when receiving broker status messages ($SYS-topics)
Feb 18

Introducing: FontAwesomeFX 8.1

I have started a new major of FontAwesomeFX.

fa81_structure

First of all the new container for an icon character now extends javafx.scene.text.Text instead of javafx.scene.control.Label (see this post for details, many thanks to Peter Schulz for the hint!).
If you know former versions of FontAwesomeFX you may notice that AwesomeDude is now called GlyphsDude, AwesomeIconsStack is now GlyphsStack and so on. But the most significant change is the option to support basically any Glyph/Web Font by just adding a new implementation GlyphIcon where T implements the GlyphIconName interface and the name -> unicode mapping (as Enum).

Currently 2 icon fonts support are build-in:

FontAwesomeIcon
(in respect to Dave Gandy http://fortawesome.github.io/Font-Awesome/ (Yes: ‘fortawesome’ its not a typo ;-)))
fa_icons

WeatherIcon
(in respect to Erik Flowers and Lukas Bischoff http://erikflowers.github.io/weather-icons/)
wi_icons

Usage in FXML

fxml_usage

<?import de.jensd.fx.glyphs.fontawesome.*?>
<?import de.jensd.fx.glyphs.weathericons.*?>

<fx:root prefHeight="300.0" prefWidth="600.0" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
    <children>
        <VBox alignment="CENTER" spacing="10.0">
            <children>
                <FontAwesomeIcon iconName="STAR" size="12em" glyphStyle="-fx-fill: linear-gradient(#70b4e5 0%, #247cbc 70%, #2c85c1 85%);"/>
                <WeatherIcon iconName="CLOUD" size="12em" glyphStyle="-fx-fill: linear-gradient(#70b4e5 0%, #247cbc 70%, #2c85c1 85%);"/>
                <StackPane>
                    <children>
                      <FontAwesomeIcon iconName="CIRCLE" size="24em" glyphStyle="-fx-fill: linear-gradient(#70b4e5 0%, #247cbc 70%, #2c85c1 85%);"/>
                      <FontAwesomeIcon iconName="BITBUCKET" size="12em" glyphStyle="-fx-fill: linear-gradient(#ffffff, #d2d2d2); -fx-effect: dropshadow( one-pass-box , rgba(0,0,0,0.8) , 4 , 0.0 , 1 , 1 );"/>
                     </children>
                </StackPane>
            </children>
            <padding>
                <Insets bottom="20.0" top="20.0" />
            </padding>
        </VBox>
    </children>
</fx:root>

Usage in SceneBuilder

Also layered combinations are supported: GlyphStack

stack

stack_code

Download Binaries: Download
Sources available at Bitbucket

Maven:

<dependency>
  <groupId>de.jensd</groupId>
  <artifactId>fontawesomefx</artifactId>
  <version>8.1</version>
</dependency>
Feb 07

MQTT.fx 0.0.14 released

As always you can download latest binaries at mqttfx.org.
Bugs and feature requests can be reported via the issue tracker.
Also the Update Feature of 0.0.13 should inform you, that there are updates available (See NNOTE 1 at bottom of this page)!

Reviewed Clipboard Messages

  • Order can now be changed by Drag-and-Drop
  • Can be published instantly by click on Button
  • Changes are now stored immediately

messages-clipboard

All new approach with topics and messages

  • Rendering revisited
  • Colors of topics can now be customized (messages are colored accordingly)
  • Colors of topics are persisted in configuration
  • Topics can now be unsubscribed by click on “-” (messaged will be removed accordingly)
  • Number of received messages per topic is shown
  • Messages also do show the wildcard topics to which they have matched
  • Only longer payloads are expandable now, one-liner are shown as subject
  • “Copy Payload” is now accessible without expanding the payload
  • Improved performance

message-rendering

topic-color

Support for HTTPS proxy connection options
In respect to Dino Tsoumakis ;-)
https proxy

Anything else?

  • Fixed an issue with unrecognized (but allowed) characters in topics

I was asked how to add new Scripts
I mentioned this before in a post (but this was 6 month ago ;-)).

New scripts can be easily made available for execution via the UI.
The app is scanning a folder named “scripts” located at the MQTT.fx working directory:

OS X
[USER_HOME]/Library/Application Support/MQTT-FX/scripts

Windows
[USER_HOME]\AppData\Local\MQTT-FX\scripts

Linux
[USER_HOME]/MQTT-FX/scripts

If this folder does not exists it is created by MQTT.fx containing scripts.
Naming convention:
[INDEX]__[NAME].js

[INDEX] controls the order of the entry in the drop down menu
__ delimiter between index and name
[NAME the name of the menu entry (words are delimit by ‘_’)

E.g.: With these files in the “scripts” folder
01__Switch_Fountain_Test.js
02__Subscribe_Publish_Unsubscribe_Test.js

the menu looks like this:
scripts menu

NOTE 1: In 0.0.13 the Update Feature has a bug!
The new install packages are loaded but yet not always renamed on Windows and Linux (this is fixed in 0.0.14). You will find the packages ending with postfix “.download”. You have to rename it manually.

NOTE 2: The format of the configuration has changed!
You may have to delete you current configuration and restart MQTT.fx. MQTT.fx will create a new default configuration for you!

Feb 06

SweetHomeHub: Home Control with Raspberry Pi and MQTT – Part 1

Since quite a long time I am working on my universal Raspberry Pi based Intertechno-Remote (see former posts 1 2 3 4):

intertechno remote

I tried different approaches to trigger/control my remote control service via a custom HTTPServer/-Handler and a simple Vert.x verticle.
Since MQTT v3.1.1 turns out as on of the de-facto standard protocols for the IoT I also implemented an MQTT client.

This MQTT client basically follows two design patterns:

1. One topic for each device
For each device a topic is defined. Its state can be controlled by publishing a message with payload “ON” or “OFF”.
Pro:

  • the user must not know about the address code of the Intertechno device
  • changes of the address must not be published
  • the message is simply “ON” or “OFF to control the device

Contra:

  • the user must know the topic for each device
  • the user can only control configured devices

2. One topic for a JSON message
Pro:

  • very flexible to control the devices

Contra:

  • the user must know about the syntax of the JSON and the coding of devices

Solution:
Provide both options ;-)

One topic for each device

topics_table

My configuration is very simple
On start-up the Client is searching for sweethomehub-config.xml in the users home directory which is then unmarshalled from JAXB.
This configuration contains the codes and the topic for each device and the MQTT settings for the broker connection:

<configuration>
    <devices>
        <device>
            <houseCode>a</houseCode>
            <groupId>1</groupId>
            <deviceId>1</deviceId>
            <name>Light Front-Door</name>
            <mqttTopic>front/lights/door</mqttTopic>
        </device>
        <device>
            <houseCode>a</houseCode>
            <groupId>1</groupId>
            <deviceId>2</deviceId>
            <name>Light Terrace</name>
            <mqttTopic>garden/lights/terrace</mqttTopic>
        </device>
        <device>
            <houseCode>a</houseCode>
            <groupId>1</groupId>
            <deviceId>3</deviceId>
            <name>Fountain</name>
            <mqttTopic>garden/devices/fountain</mqttTopic>
        </device>
        <device>
            <houseCode>a</houseCode>
            <groupId>1</groupId>
            <deviceId>4</deviceId>
            <name>Light Garden</name>
            <mqttTopic>garden/lights/ambiente</mqttTopic>
        </device>
        <device>
            <houseCode>a</houseCode>
            <groupId>1</groupId>
            <deviceId>3</deviceId>
            <name>Light Living Room</name>
            <mqttTopic>livingroom/lights/ambiente</mqttTopic>
        </device>
    </devices>
    <mqttClientConfiguration>
        <mqttClientId>SweethoemMQTTClientId</mqttClientId>
        <mqttBrokerAddress>sweethome</mqttBrokerAddress>
        <mqttBrokerPort>1883</mqttBrokerPort>
        <mqttMessagesBaseTopic>sweethome</mqttMessagesBaseTopic>
    </mqttClientConfiguration>
</configuration>

And there is one additional topic awaiting the JSON commands:
sweethome/devices/jsoncommand

{
  "devices":[
    {
      "device":{
        "name": "Light Front-Door",
        "houseCode": "a",
        "groupId": "1",
        "deviceId": "1"
      },
      "command":"ON"
    },
    {
      "device":{
        "name": "Light Terrace",
        "houseCode": "a",
        "groupId": "1",
        "deviceId": "2"
      },
      "command":"ON"
    },
    {
      "device":{
        "name": "Light Living Room",
        "houseCode": "a",
        "groupId": "1",
        "deviceId": "3"
      },
      "command":"ON"
    }
  ]
}

The central method to handle arrived messages:

MqttMessageReceiver.messageArrived

The JsonDeviceCommandProcessor:

JsonCommandProcessor

And the doSwitch methods:

DeviceControl

MQTT Client running on the Raspberry Pi waiting for messages:
mqtt-receiver

… and receiving command messages:

mqtt-receiver-commands

Testing the receiver with MQTT.fx

mqtt-fx

Complete code can be found at BitBucket.

Jan 29

FontAwesomeFX 8.0.13 released

FontAwesomeFX 8.0.13 comes with 40 new icons (FontAwesome 4.3.0)

Many thanks to Steffen Rachner for his pull request!

Download Binaries: Download
Sources available at Bitbucket

Maven:

<dependency>
  <groupId>de.jensd</groupId>
  <artifactId>fontawesomefx</artifactId>
  <version>8.0.13</version>
</dependency>
Jan 28

JFXPanel and FX Platform Thread pitfalls

The JFXPanel is a component to embed JavaFX content into (legacy ;-)) Swing applications.
Basically it makes it very easy to combine both tookits, but there are some pitfalls to master:
Both UI Toolkits are single threaded (Swing: EDT + JavaFX: FX Platform Thread). When used together you have to deal with these two threads, e.g.
javafx.embed.swing.SwingFXUtils.runOnFxThread(Runnable runnable)
or
javafx.embed.swing.SwingFXUtils.runOnEDT(Runnable rrunnable)

The FX Platform Thread is implicitly started in the constructor of the JFXPanel by initFx():

// Initialize FX runtime when the JFXPanel instance is constructed
private synchronized static void initFx() {
    // Note that calling PlatformImpl.startup more than once is OK
    PlatformImpl.startup(new Runnable() {
        @Override public void run() {
            // No need to do anything here
        }
    });
}

But (if I got it right) JFXPanel overrides addNotify() from Component where a finishListener is added to the FX-Platform ( PlatformImpl.addListener(finishListener)). Platform.exit is then called when the last JFXPanel “dies”.

This might lead into a weird situation:

When JFXPanel is used e.g. with a JDialog: The first call opens the Dialog with a new JFXPanel and all is going well.
But when this Dialog is closed the FX Platform Thread is exited and for some reasons it looks like the second call to open a new Dialog doesn’t start the FX Platform Thread again. So nothing happens on the JFXPanel!

Solution:

For me it worked to call (somewhere early in main())
Platform.setImplicitExit(false);
to prevent closing the FX Thread implicitly (its closed then by the System.exit()).

Jan 26

How to allow users to customize the UI

Idea

Take advantage of the declarative design pattern of JavafX/FXML and allow users to customize a certain view without any coding just by opening it with e.g. SceneBuilder to re-arrange the layout or add new controls or even change the style according to the users needs.

The FXML file + CSS can be basically be placed whereever they are reachable via a URL.
The user must only know the interface/methods of the assigned controller class inside the FXML.

RemoteController

Assuming this simple demo controller class provides methods to remotely control devices and to send MQTT messages, a user is able to customize his own remote control.

public class RemoteController{

    @FXML
    public void onTest(){
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setContentText("");
        alert.setHeaderText("WORKS!");
        alert.show();
    }
    
    public void onTest(String value){
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setHeaderText("WORKS!");
        alert.setContentText(value);
        alert.show();
    }
    
    public void onSwitch(String houseCode, int groudId, int deviceId, String command){
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setHeaderText("Switch!");
        alert.setContentText(String.format("Command: send %s %d %d %s", houseCode, groudId, deviceId, command));
        alert.show();
    }
}

remote.fxml and remote.css

Note the referenced de.jensd.shichimifx.demo.ext.RemoteController and remote.css.
So basically controller actions can be called via

onAction="#onTest".

Nice:
If you add

<?language javascript?>

to FXML, it’s also possible to pass parameters by a JavaScript call via the controller-instance.

onAction=controller.onTest('OFF')
onAction=controller.onSwitch('a',1,1,'ON')

Unfortunately I can’t find more documentation about this feature than -> this, but somehow it magically it works ;-). Its even possible to pass different types of parameters.

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

<?language javascript?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox alignment="TOP_CENTER" prefHeight="400.0" prefWidth="600.0" spacing="20.0" styleClass="main-pane" stylesheets="@remote.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.jensd.shichimifx.demo.ext.RemoteController">
   <children>
      <Label styleClass="title-label" text="Universal Remote" />
      <HBox alignment="CENTER_RIGHT" spacing="20.0">
         <children>
            <Label layoutX="228.0" layoutY="96.0" styleClass="sub-title-label" text="Light Frontdoor" />
            <Button layoutX="43.0" layoutY="86.0" mnemonicParsing="false" onAction="#onTest" prefWidth="150.0" styleClass="button-on" text="ON" />
            <Button layoutX="411.0" layoutY="86.0" mnemonicParsing="false" onAction="#onTest" prefWidth="150.0" styleClass="button-off" text="OFF" />
         </children>
         <padding>
            <Insets left="10.0" right="10.0" />
         </padding>
      </HBox>
      <HBox alignment="CENTER_RIGHT" spacing="20.0">
         <children>
            <Label layoutX="228.0" layoutY="96.0" styleClass="sub-title-label" text="Light Garden" />
            <Button layoutX="43.0" layoutY="86.0" mnemonicParsing="false" onAction="controller.onTest('ON')" prefWidth="150.0" styleClass="button-on" text="ON" />
            <Button layoutX="411.0" layoutY="86.0" mnemonicParsing="false" onAction="controller.onTest('OFF')" prefWidth="150.0" styleClass="button-off" text="OFF" />
         </children>
         <padding>
            <Insets left="10.0" right="10.0" />
         </padding>
      </HBox>
      <HBox alignment="CENTER_RIGHT" spacing="20.0">
         <children>
            <Label layoutX="228.0" layoutY="96.0" styleClass="sub-title-label" text="Light Garden" />
            <Button layoutX="43.0" layoutY="86.0" mnemonicParsing="false" onAction="controller.onSwitch('a', 1,1,'ON')" prefWidth="150.0" styleClass="button-on" text="ON" />
            <Button layoutX="411.0" layoutY="86.0" mnemonicParsing="false" onAction="controller.onTest('OFF')" prefWidth="150.0" styleClass="button-off" text="OFF" />
         </children>
         <padding>
            <Insets left="10.0" right="10.0" />
         </padding>
      </HBox>
   </children>
   <padding>
      <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
   </padding>
</VBox>

Based on this example a user is able to simple open the FXMl with SceneBuilder and to add new Button calling the controller.onSwitch() method to control different/new devices installed for home automation.

FxmlUtils
The next release of ShichimiFX will contain a new Utilily class to load FXML as shown in the ExternalFXMLDemoController. Note that the loaded Pane is added to the center of the externalPane (BorderPane) of the Demo-Application via onLoadExternalFxml():

public class ExternalFXMLDemoController {

    @FXML
    private ResourceBundle resources;

    @FXML
    private BorderPane externalPane;

    @FXML
    private TextField fxmlFileNameTextField;

    @FXML
    private Button chooseFxmlFileButton;

    @FXML
    private Button loadFxmlFileButton;

    private StringProperty fxmlFileName;

    public void initialize() {
        fxmlFileNameTextField.textProperty().bindBidirectional(fxmlFileNameProperty());
        loadFxmlFileButton.disableProperty().bind(fxmlFileNameProperty().isEmpty());
    }

    public StringProperty fxmlFileNameProperty() {
        if (fxmlFileName == null) {
            fxmlFileName = new SimpleStringProperty("");
        }
        return fxmlFileName;
    }

    public String getFxmlFileName() {
        return fxmlFileNameProperty().getValue();
    }

    public void setFxmlFileName(String fxmlFileName) {
        this.fxmlFileNameProperty().setValue(fxmlFileName);
    }

    @FXML
    public void chooseFxmlFile() {
        FileChooser chooser = new FileChooser();
        chooser.setTitle("Choose FXML file to load");
        if (getFxmlFileName().isEmpty()) {
            chooser.setInitialDirectory(new File(System.getProperty("user.home")));
        } else {
            chooser.setInitialDirectory(new File(getFxmlFileName()).getParentFile());
        }

        File file = chooser.showOpenDialog(chooseFxmlFileButton.getScene().getWindow());
        if (file != null) {
            setFxmlFileName(file.getAbsolutePath());
        }
    }

    @FXML
    public void onLoadExternalFxml() {
        try {
            Optional<URL> url = FxmlUtils.getFxmlUrl(Paths.get(getFxmlFileName()));
            if (url.isPresent()) {
                Pane pane = FxmlUtils.loadFxmlPane(url.get(), resources);
                externalPane.setCenter(pane);
            } else {
                Alert alert = new Alert(Alert.AlertType.WARNING);
                alert.setContentText(getFxmlFileName() + " could not be found!");
                alert.show();
            }
        } catch (IOException ex) {
            Dialogs.create().showException(ex);
        }
    }
}
Jan 16

MQTT.fx 0.0.13 released

Download latest binaries at mqttfx.org.
Bugs and feature requests can be reported via the issue tracker.

New in this version:

Extended Scripting Features

  • fixed issues with starting external editor to edit scripts
  • support for subscribe/unsubscribe to Mqtt-Scripting interface

Redesinged and extended Settings Dialog

  • option to choose whether the default system editor should be use or a custom edit command
  • option to choose whether to check for updates on app start

new-settings

settings-script

settings-update

Build in Update Feature

  • Added support Refuel API for application updates

check-updates

updates-available

updates-load

KUDOs to my friend Dino Tsoumakis for his great work on his application update tool for Java 8 “Refuel” (view on github)!

Jan 16

ShichimiFX 1.0.5 released

I have released ShichimiFX 1.0.5.

Get more info and the code from my ShichimiFX Bitbucket Repo

Maven

<dependency>
  <groupId>de.jensd</groupId>
  <artifactId>shichimifx</artifactId>
  <version>1.0.5</version>
</dependency>

UI for Refuel

This release contains a Frontend for Refuel an application update API written by Dino Tsoumakis which is used with MQTT.fx 0.0.13.

updates-available

updates-load