Monday, 23 April 2018

This week 2/2018 - JavaFX

Long time I was looking for some solution to create simple desktop application. My previous choice was SWT and JFace but I was not satisfied because of its OS dependence and different presentation depending of OS. There were some other problems with windows resizing and tree view updating.
This time when I developed something for desktop, I was looking for something what is supported by all most famous IDE and is OS independent.

I've tried JavaFX and I think it was good choice. Even a few small problems which I list in the end of article.

JavaFX  it has to be successor of Swing library. It was initialized in the end of 2008 as external library. It was included to JDK only since JDK7 update 6. Since JDK8 is a standard part of JDK/JRE and uses the same version numbering. Most common Java IDEs include scene builder GUI. The output of this tool is a fxml file which is more less an equivalent of programmatic scene creation and is updated when fxml is updated. My experience with this GUI in IntelliJ on Linux was not ideal because sometimes of rendering problems but it is helpful tool for beginner and to arrange elements on scene.

The JavaFX thread needs to be run from class extending Application class. Then creation of stage, scene have to be in JavaFX thread. The same is with every action which changes view. To make change from other thread it is required to call async method:
Platform.runLater(Runnable runnable);

Stage (representing a window) and its elements (scene nodes) can be loaded from fxml file and coded in Java as well. Fxml file is a xml file loaded during stage building.
JavaFX allows defining css styles of formulas which can be used in fxml file and java code as well.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TreeView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<AnchorPane prefHeight="400.0" prefWidth="380.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="example.TaskListController">
    <children>
        <TreeView fx:id="taskTree" layoutX="6.0" prefHeight="334.0" prefWidth="374.0" AnchorPane.bottomAnchor="65.0"
                  AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0"/>
        <Pane layoutY="338.0" prefHeight="65.0" prefWidth="470.0" AnchorPane.bottomAnchor="0.0">
            <children>
                 <TextField fx:id="taskNameInput" layoutX="70.0" layoutY="1.0" prefHeight="26.0" prefWidth="392.0"
   style="-fx-padding: 0px; -fx-border-insets: 0px; -fx-background-insets: 0px; -fx-control-inner-background:#BBB; -fx-font-size: 10px;"/>
                <CheckBox fx:id="autoClose" selected="true" layoutX="7.0" layoutY="35.0" mnemonicParsing="false" text="auto close"/>
                <Button fx:id="updateButton" layoutX="294.0" layoutY="31.0" mnemonicParsing="false" onAction="#onTaskUpdate" text="update"/>
                <Spinner fx:id="positionSpinner" amountToStepBy="1" max="1000" min="0" prefHeight="26.0"  prefWidth="104.0"/>
                <CheckBox fx:id="moveCheck" layoutX="205.0" layoutY="35.0" mnemonicParsing="false" text="move" onAction="#onMove"/>
            </children>
        </Pane>
    </children>
</AnchorPane>

I don't remember how it was in Swing but JavaFX on every user action creates an event. This is handled by hierarchy of registered by programmer event handlers. Each event has source of event, target and type. Some events can be triggered by other event, ex they change state of observed element.

Another problem was, how to test it? Hopefully there is a TestFX. It resemble a little Selenium - it is possible to find element by xpath query and execute some action. I did only a few such tests and I know that this tool has some problems with dual-screens on linux. I have to turn off one monitor to resolve problem.


Below a few problems which I met:
1. I could set only one icon for all stages.
2. CheckboxTreeItem - chain of calls, I don't know who triggered event (user/previous element in chain)
3. On linux I can't play mp3. I found out that I must install some libraries and after that it doesn't work as well.



Sunday, 28 January 2018

This week 1/2018 - IntelliJ plugin

Hi Fellows,
this time I started year from creating a tool to automate my work. I always meet with problem of creating builder, mappers and some test data filling dto/vo for test purpose.
At the beginning I started from some simple examples of such plug-ins. Then I was looking for tutorial "how to start", what is concept and what are main interfaces, files, classes required to create plug-in. Unfortunately I didn't find any good for me tutorial with diagrams and main steps. Finally I had to experiment and iteratively find the solution. Now I know the main steps and I described them below in nutshell.


1. IntelliJ project - it is easy to create new plugin project, isn't it ?

2. Plug-in information stored in path META-INF/plugin.xml.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<idea-plugin>
    <id>example</id>
    <name>Builder plugin</name>
    <version>1.0</version>
    <actions>
        <action id="builderCreator" class="intellij.BuilderAction" text="Builder creator">
            <add-to-group group-id="GenerateGroup" anchor="last"/>
        </action>
    </actions>
</idea-plugin>

The most important part is to define action, where class is extension of AnAction abstract class.


2. Dependencies - we need at least a IntelliJ IDEA SDK - define it in project structure.

3. Class hierarchy - as I wrote above, in my case the main class of plugin is AnAction. Because of error connected with startTransaction problem I found some example where was used other class BaseCodeInsightAction. As I checked its parent class overwrite startInTransaction method. Anyway this extension add a few other function. I'd like to have list of classes with sublists of class fields. This works fine with MemberChooser class.
Panels and other elements are good know from Swing and AWT.

4. Artefacts - to create module jar, you just need to execute Build -> Prepare All Plugins Modules For Deployment.

5. Import project  - when I'd like to import my sources to new IntelliJ project I had  to in a hacky way change my project iml file. Type of module from JAVA

<module type="JAVA_MODULE" version="4">

to PLUGIN

<module type="PLUGIN_MODULE" version="4">

and check path to my plugin.xml

Project Structure -> Modules -> Plugin Deployment -> Path to META-INF/plugin.xml
 
I didn't make this project as maven project. I had some problems with maven dependencies and I didn't spend much time to resolve it.