‘Font Awesome’ Icons with JavaFX: minor updates

Refer for latest updates here.

Hi,

some minor FontAwesomeFX updates:

The AwesomeDude now provides convenience methods to add an AwesomeFont-Icon to existing Labeled-controls and MenuItems by setting the graphic node:

labeled.setGraphic(createIconLabel(icon,iconSize));

Recall that direct subclasses of Labeled are ButtonBase, Cell, Label, TitledPane and their friends (by now I have not tested all combination).

setIcon(Labeled labeled, AwesomeIcon icon)
setIcon(Labeled labeled, AwesomeIcon icon, ContentDisplay contentDisplay)
setIcon(Labeled labeled, AwesomeIcon icon, String iconSize)
setIcon(Labeled labeled, AwesomeIcon icon, String iconSize, ContentDisplay contentDisplay)
setIcon(MenuItem menuItem, AwesomeIcon icon)
setIcon(MenuItem menuItem, AwesomeIcon icon, String iconSize)
setIcon(MenuItem menuItem, AwesomeIcon icon, String fontSize, String iconSize)

Usage

For example, I use the new methods for the UI of my RaspberryPi Home project:

AwesomeDude.setIcon(onButton, AwesomeIcon.LIGHTBULB, "72px");
AwesomeDude.setIcon(offButton, AwesomeIcon.LIGHTBULB, "72px");
AwesomeDude.setIcon(exitButton, AwesomeIcon.POWER_OFF, "48px");

Looks like this:

sweethomefx_1_0_1

Source
@ Bitbucket

Maven

<dependency>
  <groupId>de.jensd</groupId>
  <artifactId>fontawesomefx</artifactId>
  <version>8.0.1</version>
</dependency>

‘Font Awesome’ Icons with JavaFX revisited

Refer for latest updates here.

Hi,
while melting away during the day in the office, it is now cool enough to revisit
FontAwesome and to adjust my little project to support FontAwesome version 3.2.1.

Thus: Major Changes:

  • Added all new version 3.2.1 icons (now 361 icons in total).
  • Removed leading “ICON_” from AwesomeIcon Enum (AwesomeIcon.GEARS instead of AwesomeIcon.ICON_GEARS).
  • Easier usage: Font is automatically loaded. Just use the factory methods provided by the dude.
  • Size parameters are String now to support different values, e.g. “2em”

Usage:

public class App extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
       
     
        Label githubLabel = AwesomeDude.createIconLabel(AwesomeIcon.GITHUB);
        Label ambulanceLabel = AwesomeDude.createIconLabel(AwesomeIcon.AMBULANCE, "60.0");
        Button starButton = AwesomeDude.createIconButton(AwesomeIcon.STAR, "Nice!", "60.0", "20.0", ContentDisplay.TOP);
        Button cloudButton = AwesomeDude.createIconButton(AwesomeIcon.CLOUD, "Download");
        ToggleButton toggleButton = AwesomeDude.createIconToggleButton(AwesomeIcon.LOCK, "Lock", "60.0", ContentDisplay.TOP);

        ToggleButton serverButton = AwesomeDude.createIconToggleButton(AwesomeIcon.DASHBOARD, "Domain", "3em", ContentDisplay.TOP);
        ToggleButton configurationButton = AwesomeDude.createIconToggleButton(AwesomeIcon.GEARS, "Config", "3em", ContentDisplay.TOP);
        ToggleButton settingsButton = AwesomeDude.createIconToggleButton(AwesomeIcon.FILE_TEXT, "Settings", "3em", ContentDisplay.TOP);
        ToggleButton updateButton = AwesomeDude.createIconToggleButton(AwesomeIcon.DOWNLOAD, "Update", "3em", ContentDisplay.TOP);
        ToggleButton aboutButton = AwesomeDude.createIconToggleButton(AwesomeIcon.INFO_SIGN, "About", "3em", ContentDisplay.TOP);

        SegmentedButton segmentedButton = new SegmentedButton(serverButton, configurationButton, settingsButton, updateButton, aboutButton);

        ToggleButton serverButtonBig = AwesomeDude.createIconToggleButton(AwesomeIcon.DASHBOARD, "Domain", "10em", ContentDisplay.TOP);
        ToggleButton configurationButtonBig = AwesomeDude.createIconToggleButton(AwesomeIcon.GEARS, "Config", "10em", ContentDisplay.TOP);
        ToggleButton settingsButtonBig = AwesomeDude.createIconToggleButton(AwesomeIcon.FILE_TEXT, "Settings", "10em", ContentDisplay.TOP);
        ToggleButton updateButtonBig = AwesomeDude.createIconToggleButton(AwesomeIcon.DOWNLOAD, "Update", "10em", ContentDisplay.TOP);
        ToggleButton aboutButtonBig = AwesomeDude.createIconToggleButton(AwesomeIcon.INFO_SIGN, "About", "10em", ContentDisplay.TOP);

        SegmentedButton segmentedButtonBig = new SegmentedButton(serverButtonBig, configurationButtonBig, settingsButtonBig, updateButtonBig, aboutButtonBig);
        VBox root = new VBox();
        root.getChildren().addAll(githubLabel, ambulanceLabel, starButton, cloudButton, toggleButton, segmentedButton, segmentedButtonBig);

        Scene scene = new Scene(root, 500, 500);
        scene.getStylesheets().addAll(AwesomeStyle.BLUE.getStylePath());

        primaryStage.setScene(scene);
        primaryStage.setTitle("FontAwesomeFX demo");
        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
}

With added stylesheet:

FontAwesome2

Without any additional styles:

FontAwesome1

Source can be found here:
FontAwesomeFX
FontAwesomeFX-Demo

Maven artifact:

<dependency>
    <groupId>de.jensd</groupId>
    <artifactId>fontawesomefx</artifactId>
    <version>8.0.0</version>
</dependency>

See also:
Griffon Plugin – fontawesome-javafx by Andres Almiray
Font Awesome usage with Swing (yes, Swing is still alive 😉 ) by Mario Torre

RasPi does the Home Automation (Part IV): Cut the ‘rope’

Hi all,

until now all UI-Actions to control my wireless gears had to run directly on the Pi which controls the remote as e.g. deviceControl.turnOn(device); is called.

But now I’d rather make a web service available for this purpose to be more independently.
Question is: Which server should I use?

  • Apache/PHP: too less Java 😉
  • GlassFish/Java EE: too fat for this purpose and hard to take for a RasPi

But wait a minute: wasn’t there a HttpServer class that comes with Java6?
Using HttpServer I wrote a very small Server to provide the desired service.

Now I can switch my devices by an URL like this:

http://RASPI-IP:PORT/CONTEXT?houseCode=HOUSE-CODE&group=GROUP&device=DEVICE&command=COMMAND

e.g. http://raspi.home:22222/homeserver?houseCode=a&group=1&device=2&command=1

SEND URL:
RasPi_HomeServer1

SERVER (RE-)ACTION:
RasPi_HomeServer2

Recently my Pi received a command from Madrid (thanks José for supporting me ;-)):

2013-07-18 08_53_13-Twitter _ Interactions

For a more convenient usage with e.g. an JavaFX-EventHandler I use a HttpCommand to act like a DeviceContol:

public class SendHttpCommand {

    public static void main(String[] args) {
        Settings settings = new Settings();
        HttpCommand httpCommand = new HttpCommand(settings.getProperty("sweethome.server.ip.local"));
        Device terrace = new Device("Terrace", "a", "1", "2");
        String result = httpCommand.turnOn(terrace);
        System.out.println(result);
    }
}

Now the DevicePane looks like this:

public class DevicePane extends AnchorPane {

    @FXML
    private Button offButton;
    @FXML
    private Button onButton;
    @FXML
    private Text deviceNameText;

    private Device device;
    
    private DeviceControl deviceControl;
    private HttpCommand httpCommand;
    
    public DevicePane(final Device device) {
        this.device = device;
        init();
    }

    private void init() {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/DevicePane.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        } catch (IOException ex) {
            Logger.getLogger(DevicePane.class.getName()).log(Level.SEVERE, null, ex);
        }

        Settings settings = new Settings();
        httpCommand = new HttpCommand(settings.getProperty("sweethome.server.ip.local"));
        
        deviceControl = new DeviceControl();
        
        deviceNameText.setText(device.getName());

        offButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                turnOff();
            }
        });

        onButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                turnOn();
            }
        });
    }

    private void turnOn() {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                deviceControl.turnOn(device);
                httpCommand.turnOn(device);
            }
        });

    }

    private void turnOff() {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                deviceControl.turnOff(device);
                httpCommand.turnOff(device);
            }
        });

    }
}

RasPi does the Home Automation (Part III): ‘Let’s Put It All Together’

Hi,
now it’s time to put it all together:
1st: a mini Custom Control for each gear, looking like this:

Gear

Its controller takes a Device to trigger DeviceControl to switch the radio controlled gears:

public class DevicePane extends AnchorPane {

    @FXML
    private Button offButton;
    @FXML
    private Button onButton;
    @FXML
    private Text deviceNameText;


    public DevicePane(Device device) {
        init(device);
    }

    private void init(final Device device) {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/DevicePane.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        } catch (IOException ex) {
            Logger.getLogger(DevicePane.class.getName()).log(Level.SEVERE, null, ex);
        }

        deviceNameText.setText(device.getName());

        offButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                DeviceControl.get().turnOff(device);
            }
        });

        onButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                DeviceControl.get().turnOn(device);
            }
        });
    }
}

Finally the main controller HomeControlBoardController creates DevicePanes based on the configuration:

public class HomeControlBoardController {

    @FXML
    private Button exitButton;
    @FXML
    private AnchorPane root;
    @FXML
    private VBox devicesPane;

    public HomeControlBoardController() {
    }

    @FXML
    void initialize() {
        assert devicesPane != null : "fx:id=\"devicesPane\" was not injected: check your FXML file 'HomeControlBoard.fxml'.";
        assert exitButton != null : "fx:id=\"exitButton\" was not injected: check your FXML file 'HomeControlBoard.fxml'.";
        assert root != null : "fx:id=\"root\" was not injected: check your FXML file 'HomeControlBoard.fxml'.";

        // Running on RasPi always provide a way out instead of kill command
        final EventHandler<KeyEvent> exitOnCrtlCEventHandler =
                new EventHandler<KeyEvent>() {
            @Override
            public void handle(final KeyEvent keyEvent) {
                if (keyEvent.isControlDown() && KeyCode.C.equals(keyEvent.getCode())) {
                    Platform.exit();
                    keyEvent.consume();
                }
            }
        };
        root.setOnKeyPressed(exitOnCrtlCEventHandler);
        
        List<Device> devices = DeviceLoader.load();

        for (Device device : devices) {
            addDevice(device);
        }
    }

    private void addDevice(Device device) {
        DevicePane devicePane = new DevicePane(device);
        devicesPane.getChildren().add(devicePane);
    }

    @FXML
    public void exit() {
        Platform.exit();
    }
}

So finally (by now) it looks like this:

HomeControl2

Next: RasPi does the Home Automation (Part IV): Cut the ‘rope’

RasPi does the Home Automation (Part II): Crossing the bridge to JavaFX

Hi,

before JavaFX can take over, I need some bottom-up stuff to control my Intertechno-Devices.

Basically this is the schema:
RaspiSendSetup

Right now I have 2 radio intermediate adapters to switch the lights of my terrace/garden and the fountain. And one of these to control the lights in front of my house (cool: can be combined with existing light switch) :
ITL-230_assembly

Some Details:

Pragmatic approach: “Runtime.getRuntime().exec(...)
Clearly to pipe the data to the C implementation via a JNI call would be nice, but to get ahead in time by now for me it’s ok to use Runtime.getRuntime().exec(...) to run my “send” CLI command:

 public class Send {

  public enum Command {
    TURN_OFF, TURN_ON;
  }

  public static final String SEND_COMMAND = "/home/pi/rcswitch-pi/send";
  private static final Logger logger = Logger.getLogger(Send.class.getName());

  public void send(String deviveCode, Command command) {
    try {
      String commandLine = String.
              format("%s %s %s", SEND_COMMAND, deviveCode, command.ordinal());
      logger.log(Level.INFO, "send: {0}", commandLine);

      Runtime rt = Runtime.getRuntime();
      Process pr = rt.exec(commandLine);
      BufferedReader rd = new BufferedReader(new InputStreamReader(pr.
              getInputStream()));
      String line;
      while ((line = rd.readLine()) != null) {
        logger.log(Level.INFO, line);
      }

    } catch (IOException ex) {
      Logger.getLogger(Send.class.getName()).
              log(Level.SEVERE, null, ex);
    }
  }
  
  public boolean isSendCommandExecutable(){
      return Files.isExecutable(Paths.get(SEND_COMMAND));
  }
}

The Java-Send is used by DeviceControl:

public class DeviceControl {

    private Send send = new Send();
    private static final Logger logger = Logger.getLogger(DeviceLoader.class.getName());
    private static DeviceControl me;

    private DeviceControl() {
    }

    public static DeviceControl get() {
        if (me == null) {
            me = new DeviceControl();
        }
        return me;
    }

    public void turnOn(Device device) {
        logger.log(Level.INFO, "About to {0} {1} ({2})", new Object[]{Send.Command.TURN_ON, device.getName(), device.getId()});
        if (send.isSendCommandExecutable()) {
            send.send(device.getId(), Send.Command.TURN_ON);
        } else {
            logger.log(Level.SEVERE, "{0} could not be executed!", Send.SEND_COMMAND);
        }
    }

    public void turnOff(Device device) {
        logger.log(Level.INFO, "About to {0} {1} ({2})", new Object[]{Send.Command.TURN_OFF, device.getName(), device.getId()});
        if (send.isSendCommandExecutable()) {
            send.send(device.getId(), Send.Command.TURN_OFF);
        } else {
            logger.log(Level.SEVERE, "{0} could not be executed!", Send.SEND_COMMAND);
        }
    }
}

A Intertechno-appliance is represented by Device:

public class Device {

  private String name;
  private String houseCode;
  private String group;
  private String device;

  public Device() {
  }

  public Device(String name, String houseCode, String group, String device) {
    this.name = name;
    this.houseCode = houseCode;
    this.group = group;
    this.device = device;
  }

  public String getId() {
    return String.format("%s %s %s", houseCode, group, device);
  }

 [.... getter & setter ....]

}

The available Devices are defined via a configuration-file:

<?xml version="1.0" encoding="UTF-8"?>
<home-configuration>
    <devices>
        <device name="Haustür" houseCode="a" group="1" device="1"/>
        <device name="Terrasse" houseCode="a" group="1" device="2"/>
        <device name="Springbrunnen" houseCode="a" group="1" device="3"/>
    </devices>
</home-configuration>

Finally utility class DeviceLoader.load(); loads the configuration and provides a List of Devices.
The HomeControlBoardController dynamically creates DevicePanes according to the configured devices.

That’s it for now.

Next:
RasPi does the Home Automation (Part III): ‘Let’s Put It All Together’

JavaFX 8 embedded currently ‘untouchable’?

[UPDATE]
Solved: eGalax Touch Screen issues with JavaFX (on Raspberry Pi)

Hi all,

yesterday I recevied my 7″ touch screen. I immediately started to give it a try. In the end spend the night with getting it work with my RasPi.

First with X11

Installed pre-configured kernel with eGalax touch screen support: Works!

raspi_touch1.pnp

startx: Works!

Now the really interesting part: JavaFX

For basic test purposes I added a TouchEventHandler to the root pane:

final EventHandler<TouchEvent> exitOnTouchEventHandler =
                new EventHandler<TouchEvent>() {
            @Override
            public void handle(TouchEvent t) {
                System.out.println(t.getTouchPoint().getScreenX());
                System.out.println(t.getTouchPoint().getScreenY());
                Platform.exit();
                t.consume();
            }
        };

        root.setOnTouchPressed(exitOnTouchEventHandler);
        root.setOnTouchReleased(exitOnTouchEventHandler);

Sadly: nothing happened

Then I pulled out the USB connection of the touch device and the app closed immediately with compliance of the event loop:

raspi_touch2.pnp

So I guess this indicates that basically the device is recognized by the JVM. But TouchEvents are not handled the expected way.
Anyway this urged me to give it a try some more times with other settings, but then gave up without success.

This morning Gerrit Grunwald told me, the next released build of Embedded JDK 8 will probably support ‘touch’, along with some other cool stuff like increased performance and media support (also WebView?).
Let’s hope the very best.

Meanwhile I will have to continue with good old pointing device…
(in memory of Douglas C. Engelbart)