<commit_before>![TornadoFX Logo](graphics/tornado-fx-logo.png?raw=true "TornadoFX")
# TornadoFX

Lightweight JavaFX Framework for Kotlin

[![Travis CI](https://travis-ci.org/edvin/tornadofx.svg)](https://travis-ci.org/edvin/tornadofx)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/no.tornado/tornadofx/badge.svg)](https://search.maven.org/#search|ga|1|no.tornado.tornadofx)
[![Apache License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)

## Features

- Dependency injection
- Type safe builders
- Async task execution
- MVC
- Extremely light weight
- Small, easy to grasp API
- REST client with automatic JSON conversion
- Zero config, no XML, no annotations

## Getting started

- [Wiki](https://github.com/edvin/tornadofx/wiki)
- [User Forum](https://groups.google.com/forum/#!forum/tornadofx)
- [Dev Forum](https://groups.google.com/forum/#!forum/tornadofx-dev)
- [Stack Overflow](http://stackoverflow.com/questions/ask?tags=tornadofx)
- [Documentation](https://github.com/edvin/tornadofx/wiki/Documentation) 
- [Example Application](https://github.com/edvin/tornadofx-samples) 
- [Maven QuickStart Archetype](https://github.com/edvin/tornadofx-quickstart-archetype) 
- [Changelog](CHANGELOG.md)

### Generate a quickstart application with Maven

```bash
mvn archetype:generate -DarchetypeGroupId=no.tornado \
  -DarchetypeArtifactId=tornadofx-quickstart-archetype \
  -DarchetypeVersion=1.0.2
```
> Remember to update TornadoFX version to latest

### Add TornadoFX to your project

#### Maven

```xml
<dependency>
	<groupId>no.tornado</groupId>
	<artifactId>tornadofx</artifactId>
	<version>1.4.2</version>
</dependency>
```

### Gradle

```groovy
compile 'no.tornado:tornadofx:1.4.2'
```

### What does it look like? (Code snippets)

Create a View

```kotlin
class HelloWorld : View() {
	override val root = HBox(Label("Hello world")) 
}
```
    
Load the root node from `HelloWorld.fxml` and inject controls by `fx:id`
  
```kotlin
class HelloWorld : View() {
	override val root: HBox by fxml()
	val myLabel: Label by fxid()
	
	init {
		myLabel.text = "Hello world"
	}
}
```

Start your application and show the primary `View` by extending the `App` class
    
```kotlin
class HelloWorldApp : App {
	override val primaryView = HelloWorld::class

	init {
		importStylesheet("/styles.css")
	}
}
```
> Start app and load a stylesheet

Use [Type Safe Builders](https://github.com/edvin/tornadofx/wiki/Type-Safe-Builders) to quickly create complex user interfaces

```kotlin
class MyView : View() {

    override val root = VBox()

    private val persons = FXCollections.observableArrayList<Person>(
            Person(1,"<NAME>",LocalDate.of(1981,12,4)),
            Person(2,"<NAME>",LocalDate.of(2001,1,23)),
            Person(3,"<NAME>",LocalDate.of(1989,5,23)),
            Person(3,"<NAME>",LocalDate.of(1998,8,11))
    )

    init {
        with(root) {
            tableview<Person> {
                items = persons
                column("ID", Person::id)
                column("Name", Person::name)
                column("Birthday", Person::birthday)
                column("Age", Person::age)
            }
        }
    }
}
```

**RENDERED UI**
<commit_msg>Added missing space to README<commit_after>![TornadoFX Logo](graphics/tornado-fx-logo.png?raw=true "TornadoFX")
# TornadoFX

Lightweight JavaFX Framework for Kotlin

[![Travis CI](https://travis-ci.org/edvin/tornadofx.svg)](https://travis-ci.org/edvin/tornadofx)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/no.tornado/tornadofx/badge.svg)](https://search.maven.org/#search|ga|1|no.tornado.tornadofx)
[![Apache License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)

## Features

- Dependency injection
- Type safe builders
- Async task execution
- MVC
- Extremely light weight
- Small, easy to grasp API
- REST client with automatic JSON conversion
- Zero config, no XML, no annotations

## Getting started

- [Wiki](https://github.com/edvin/tornadofx/wiki)
- [User Forum](https://groups.google.com/forum/#!forum/tornadofx)
- [Dev Forum](https://groups.google.com/forum/#!forum/tornadofx-dev)
- [Stack Overflow](http://stackoverflow.com/questions/ask?tags=tornadofx)
- [Documentation](https://github.com/edvin/tornadofx/wiki/Documentation) 
- [Example Application](https://github.com/edvin/tornadofx-samples) 
- [Maven QuickStart Archetype](https://github.com/edvin/tornadofx-quickstart-archetype) 
- [Changelog](CHANGELOG.md)

### Generate a quickstart application with Maven

```bash
mvn archetype:generate -DarchetypeGroupId=no.tornado \
  -DarchetypeArtifactId=tornadofx-quickstart-archetype \
  -DarchetypeVersion=1.0.2
```
> Remember to update TornadoFX version to latest

### Add TornadoFX to your project

#### Maven

```xml
<dependency>
	<groupId>no.tornado</groupId>
	<artifactId>tornadofx</artifactId>
	<version>1.4.2</version>
</dependency>
```

### Gradle

```groovy
compile 'no.tornado:tornadofx:1.4.2'
```

### What does it look like? (Code snippets)

Create a View

```kotlin
class HelloWorld : View() {
	override val root = HBox(Label("Hello world")) 
}
```
    
Load the root node from `HelloWorld.fxml` and inject controls by `fx:id`
  
```kotlin
class HelloWorld : View() {
	override val root: HBox by fxml()
	val myLabel: Label by fxid()
	
	init {
		myLabel.text = "Hello world"
	}
}
```

Start your application and show the primary `View` by extending the `App` class
    
```kotlin
class HelloWorldApp : App {
	override val primaryView = HelloWorld::class

	init {
		importStylesheet("/styles.css")
	}
}
```
> Start app and load a stylesheet

Use [Type Safe Builders](https://github.com/edvin/tornadofx/wiki/Type-Safe-Builders) to quickly create complex user interfaces

```kotlin
class MyView : View() {

    override val root = VBox()

    private val persons = FXCollections.observableArrayList<Person>(
            Person(1, "<NAME>", LocalDate.of(1981,12,4)),
            Person(2, "<NAME>", LocalDate.of(2001,1,23)),
            Person(3, "<NAME>", LocalDate.of(1989,5,23)),
            Person(3, "<NAME>", LocalDate.of(1998,8,11))
    )

    init {
        with(root) {
            tableview<Person> {
                items = persons
                column("ID", Person::id)
                column("Name", Person::name)
                column("Birthday", Person::birthday)
                column("Age", Person::age)
            }
        }
    }
}
```

**RENDERED UI**

{'fraction_non_alphanumeric': 0.1546203110704483, 'fraction_numerical': 0.015248551387618176, 'mean_word_length': 3.7494569152787833, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 35, 'https://': 24, 'lorem ipsum': 0, 'www.': 2, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2574817', 'n_tokens_mistral': 2428, 'n_tokens_neox': 2259, 'n_words': 442}