Tristan971/EasyFXML

View on GitHub
easyfxml/README.md

Summary

Maintainability
Test Coverage
# EasyFXML
A tiny opinionated framework for integrating _JavaFX_ with _Spring Boot_ seamlessly

[![Maven Central](https://img.shields.io/maven-central/v/moe.tristan/easyfxml.svg?style=for-the-badge)](https://search.maven.org/artifact/moe.tristan/easyfxml)

## Required dependencies
EasyFXML is based on, and requires the following runtime setup:
- **[Java 11](https://adoptopenjdk.net/?variant=openjdk11&jvmVariant=hotspot)** *with first-class support for the module-path if you use it*, 
- **[OpenJFX 11](https://openjfx.io/)** via Maven,
- **[Spring Boot 2](https://spring.io/projects/spring-boot)** via Maven

It **might** still work on different environment set-ups, but there is no official support for it.

Especially considering that JavaFX applications are expected to be bundled with their own JDK and dependencies, this
should not be an issue.

## Features

- Full support of both classpath and module path
- Declarative and type-safe definition and usage of visual components
- Easier asynchronous management of components' lifecycle
- Built with first-class support for FXML files
- No specific configuration needed

## Philosophy

The idea of EasyFXML is to adopt the industry-standard MVC model for UI components and apply it to _JavaFX_.
This allows easier  separation of concerns and lifecycle management of these components inside applications.

There are thus three core elements that go into a UI component (an **[`FxmlComponent`](src/main/java/moe/tristan/easyfxml/api/FxmlComponent.java)** hereafter):
- For the **M**odel, it is simple as your standard classes are just provided and usable via Java itself, and services and other more complex things 
can be injected via _Spring_'s autowiring system.
- The **V**iew, a standard `.fxml` file in the form of an **[`FxmlFile`](src/main/java/moe/tristan/easyfxml/api/FxmlFile.java)**
- And **C**ontroller, that is, **a Spring Bean** implementing **[`FxmlController`](src/main/java/moe/tristan/easyfxml/api/FxmlController.java)**

## Getting started

This section is mostly an (extremely) simple example, available in the
[samples module](../easyfxml-samples), under [Hello World](../easyfxml-samples/easyfxml-sample-hello-world) if you want 
to check it out for yourself. Other more complex examples are available there.

So, let's see how building a very minimal greeter window, like follows, would work:

![Hello World Sample Screenshot](../easyfxml-samples/easyfxml-sample-hello-world/doc/sample-hello-world.png)

For this you will need:
- The component's `FxmlComponent`
- An entrypoint for the UI
- A main class

##### Component ([`FxmlComponent`](src/main/java/moe/tristan/easyfxml/api/FxmlComponent.java))
```java
@Component
public class HelloComponent implements FxmlComponent {
    
    @Override 
    public FxmlFile getFile() {
        return () -> "HelloView.fxml"; 
    }

    @Override
    public Class<? extends FxmlController> getControllerClass() {
        return HelloController.class; 
    }

}
```

##### Controller ([`FxmlController`](src/main/java/moe/tristan/easyfxml/api/FxmlController.java))
```java
@Component
public class HelloController implements FxmlController {

    @FXML 
    private TextField userNameTextField;
    
    @FXML 
    private Button helloButton;
    
    @FXML 
    private HBox greetingBox;
    
    @FXML 
    private Label greetingName;

    @Override
    public void initialize() { // called once loading is fully done
        greetingBox.setVisible(false);
        greetingName.textProperty().bind(userNameTextField.textProperty());

        setOnClick(helloButton, () -> greetingBox.setVisible(true));
    }

}
```
Note that if you can have multiple instances of a given component (a notification panel, or a individual cell in a list/table for example), 
you need to make sure that the controller class is not a singleton with @Scope(scopeName = ConfigurableBeanFactory.PROTOTYPE)

##### Entrypoint of the UI ([`FxUiManager`](src/main/java/moe/tristan/easyfxml/FxUiManager.java))
###### (called by EasyFXML once JavaFX and Spring are both ready to use)
```java
@Component
public class HelloWorldUiManager extends FxUiManager {

    private final HelloComponent helloComponent;

    @Autowired
    public HelloWorldUiManager(HelloComponent helloComponent) {
        this.helloComponent = helloComponent;
    }

    @Override
    protected String title() {
        return "Hello, World!";
    }

    @Override
    protected FxmlComponent mainComponent() { // defines what component must be loaded first into the main stage
        return helloComponent;
    }

}
```

##### Main class ([`FxApplication`](src/main/java/moe/tristan/easyfxml/FxApplication.java))
```java
@SpringBootApplication // EasyFXML wires itself in the context via Spring Boot's autoconfiguration
public class HelloWorld extends FxApplication { // FxApplication is essential here to set-up JavaFX
    public static void main(String[] args) {    // and Spring cohabitation
        launch(args);
    }
}
```

And that's about all we need here. 

Feel free to look into [the samples](../easyfxml-samples) if you want to see more advanced examples!