Fluid 0.7.0 has been released!

cookiewitch artha at samerion.com
Thu Oct 3 11:15:16 UTC 2024


After 9 months of development and 252 commits later, finally 
0.7.0 gets to see the sunlight! This is the biggest update to 
Fluid yet, almost twice as big as 
[0.6.0](https://git.samerion.com/Samerion/Fluid/releases/tag/v0.6.0), and also almost half the size of Fluid itself. In fact, so big, that I decided to delay some of the changes to a [separate future update](https://git.samerion.com/Samerion/Fluid/milestone/19); too big.

**[Fluid is a general-purpose user interface 
library](https://git.samerion.com/Samerion/Fluid)**. It is D 
first, and comes with Raylib support. While largely a work in 
progress, and of pre-release quality, it's already mostly stable 
and ready for use.

Start a new Fluid project [with DUB](https://fluid.dub.pm):

```shell
dub fetch fluid
dub init -t fluid myproject
```

Add Fluid to your existing project:

```
dub add fluid
```

Among other stuff, this update addresses feedback from community 
members. Folks reported a lot of issue with building this thing. 
Fluid now has CI coverage and should work just fine on all the 
three major platforms. Fluid's tour now also features an 
experimental, fully interactive "moduleView" chapter, which at 
the moment only works properly on Linux.

In short term, I hope to improve Fluid's documentation and add a 
number of missing features, mostly nodes. In long term, I would 
like to work on animations and reactive programming.

[Full changelog can be seen on the releases 
page](https://git.samerion.com/Samerion/Fluid/releases/tag/v0.7.0)

## Reworked theme system

Most importantly, 0.7.0 introduces a reworked theme system, one 
much more readable than the last:

```d
import fluid.theme;  // explicit import needed!

auto theme = Theme(
     rule!Node(
         typeface        = Style.loadTypeface("noto.ttf"),
         fontSize        = 12.pt,
         textColor       = color("#fff"),
     ),
     rule!Frame(
         backgroundColor = color("#000"),
     ),
);
```

`when` rules can be used to alter the style based on any of the 
node's properties. Multiple `when` rules can be applied at the 
same time.

```d
border          = 1,
borderStyle     = colorBorder(color("#444")),
backgroundColor = color("#000"),
when!"a.isHovered"(
     backgroundColor = color("#444"),
),
when!"a.isFocused"(
     borderStyle = colorBorder(color("#fff")),
),
when!(a => a.text.isValidPassword)(
     backgroundColor = color(color("#0a0")),
),
```

Rules can now also affect children nodes through `children`:

```d
rule!PopupFrame(
     border = 1,
     borderStyle = colorBorder(color("#555")),
     children!Button(  // style all buttons inside PopupFrames
         margin = 0,
         padding.sideX = 4,
         padding.sideY = 2,
     )
),
```

For more advanced usecases, values can also be picked based on 
runtime values:

```d
rule!Node(
     a => rule(
         backgroundColor = pickColor(a.score),
     ),
),
```

## Extensible construction via node builder

[This feature was covered on this year's 
DConf!](https://youtu.be/AzezZhvIyS4?t=21141)

In the previous releases, `Layout` and `Theme` were taken 
directly as constructor arguments, which could be really 
confusing, and at the same time, limiting. Now, the `nodeBuilder` 
takes care of this automatically:

```d
alias label = nodeBuilder!Label;
class Label : Node {
     this(string text) {
         // ...
     }
     // ...
}

label(
     .layout!"fill",
     .myTheme,
     "Hello, World!"
),
```

More interestingly, it's now extensible — for example, 
`sizeLimit` can be used with `sizeLock` nodes:

```d
sizeLock!label(
     .sizeLimitX = 400,
     .layout!"fill",
     .myTheme,
     "Hello, World!"
)
```

You can define your own node property by creating a struct with 
an `apply` method:

```d
auto hidden(bool value = true) {
     static struct Hidden {
         bool value;
         void apply(Node node) {
             node.isHidden = value;
         }
     }
     return Hidden(value);
}

label(
     .hidden,
     "I'm invisible!"
),
```

Other node properties are now available: `.tags` (see below), 
`.ignoreMouse`, `.hidden` and `.disabled`.

`simpleConstructor` remains alive as an alias to `nodeBuilder`.

## Tags

One can now define an enum marked `@NodeTag` to create *tags*. 
These are very similar to [CSS 
classes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/class), making it possible to change how a node is styled in a consistent, predictable manner:

```d
@NodeTag
enum Tag {
     heading,
     red,
}

vspace(
     myTheme,
     label(
         .tags!(Tag.heading),
         "This is a heading!"
     ),
     label(
         .tags!(Tag.red),
         "Red text!"
     ),
	label(
         .tags!(Tag.heading, Tag.red),
         "Red heading!"
     ),
);
```

Use tags in your theme by passing them into a `rule` argument:

```d
rule!(Label, Tag.heading)(
     fontSize = 22.pt,
),
rule!(Label, Tag.red)(
     textColor = color("#f00"),
).
```
## TextInput was overhauled

TextInput now supports multiline input via `.multiline`, the 
caret can now be moved around, text can be selected, copied, 
pasted, and changes can be undone or redone with keyboard 
shortcuts.

```d
textInput();  // single line
lineInput();  // single line
multilineInput();       // multiline
textInput(.multiline);  // multiline
codeInput();  // code editor
```

This is a massive change under the hood. Fluid's text rendering 
is now a lot more performant, and can support rendering pages of 
text without slowdowns. Editing performance still needs some 
improvements.

A code editor is now available with `CodeInput` with support for 
syntax highlighting and automatic indentation. Performance issues 
are especially visible with this one, but it is expected they 
will be fixed in coming releases.

[Full changelog can be seen on the releases 
page](https://git.samerion.com/Samerion/Fluid/releases/tag/v0.7.0)



More information about the Digitalmars-d-announce mailing list