Kolibri - A GUI framework made to be as lightweight as its namesake

What is Kolibri?

Kolibri is an embedded Immediate Mode GUI mini-framework very strongly inspired by egui. Kolibri is designed to be dead simple.

Quick Overview

All examples used in this section can also be found in the examples folder. Large amounts of documentation aren't available yet, but will be added before Kolibri reaches 0.1.0

Super simple, hyper-effective

Iterate super-quickly, design GUIs like you would write a word document, and run it on literally anything - in minutes.

```rust fn main() { // ... setup code

let mut i = 0;

loop { // create the UI each frame let mut ui = Ui::newfullscreen(&mut display, medsizergb565_style());

// ... input code

ui.clear_background();

ui.add(Label::new("Basic Example").with_font(ascii::FONT_10X20));

ui.add(Label::new("Basic Counter (7LOC)"));

if ui.add_horizontal(Button::new("-")).clicked() {
  i = i.saturating_sub(1);
}
ui.add_horizontal(Label::new(format!("Clicked {} times", i).as_ref()));
if ui.add_horizontal(Button::new("+")).clicked() {
  i = i.saturating_add(1);
}

// ... simulator code

} } ```

Those 11 Lines of code will produce this GUI:

basic-example

Yes, that's really everything. No boilerplate, no nothing. If you want to see the full code using the embedded-graphics-simulator, look at the basic-example.rs file in the examples folder. (note that you need sdl2 installed to run the simulator)

Hyper-optimized for performance

Incremental Redrawing

Using Kolibri's Smartstate System allows you to only redraw what's actually needed. This enables even super-slow screens to run at faster than the human eye can see.

smartstate-example

So, how much extra code does this need? There's two things you need to do: 1. Initialize a SmartstateProvider with the number of smartstates you want to use 2. Add a smartstate to each widget you want to be smartstate-reactive

Also, you need to tell the smartstate provider when a widget needs to be forced to redraw.

```rust fn main() { // [...]

// initialize smartstate provider let smartstates = SmartstateProvider::<10>::new();

// clear the background only once Ui::newfullscreen(&mut display, medsizergb565style()).clearbackground().unwrap();

loop { // [...]

// restart the counter at the start (or end) of the loop
smartstates.restart_counter();

// add a smartstate to each widget
ui.add(Label::new("Basic Example").with_font(ascii::FONT_10X20).smartstate(smartstates.next()));

// [...]

if ui.add_horizontal(Button::new("-").smartstate(smartstates.next())).clicked() {
  i = i.saturating_sub(1);
  smartstates.next().force_redraw()
}
ui.add_horizontal(Label::new(format!("Clicked {} times", i).as_ref()).smartstate(smartstates.next()));

// [...]

} } ```

For this hassle, you get a speedup of around 15x on an ILI9341 SPI display for the example above, and over 100x for more complicated GUIs.

Note:

This will probably be changed to be automatic in the future, which would remove the need for the smartstate method, but also be a breaking change.

Smart Buffering

Using a Full-Frame Buffer is often not possible on embedded devices, due to memory constraints. Kolibri allows you to use a small buffer, in which each widget is drawn if it is small enough to fit. This allows you the same speed (or even faster speeds because of incremental redrawing) as a full-frame buffer, while using only a fraction of the memory.

```rust

// Initialize the buffer somehow fn main() { // [...]

let mut buffer = [Rgb565::CSS_BLACK; 100 * 60 /* guess your maximum widget size approximately */];

// [...]

loop { // [...]

// create the UI each frame
let mut ui = Ui::new_fullscreen(&mut display, medsize_rgb565_style());

// set the buffer
ui.set_buffer(&mut buffer);

// [...]

}

} ```

Using a buffer completely eliminates flickering while redrawing, and speeds up the drawing considerably (up to 3x faster on an ILI9341 SPI display).

Theming

Kolibri comes with a built-in theming system, which allows you to easily change the look of your GUI. Almost all aspects can be customized, from the colors down to the font, icon spacing, size, and more.

This allows you to create themes for any PixelColor type (e.g. Black and White for e-ink screens), and even switch themes at runtime.

theme-example

(themes from left to right: Dark, Blue, Light, Retro)

Compatible with everything

Kolibri is based on the embedded-graphics crate, which means that it can be used with practically any display driver for Rust. Kolibri's dead simple input system allows you to use any input device that can give you an (x, y) point on your screen, like touch screen drivers, or mouse pointers.

Further input device support (e.g. a simulated mouse cursor, or an encoder-based input system) are planned, but not yet available. If you need those for a project, feel free to open an issue or a pull request.

Current State

Kolibri is maturing at a fast pace. Right now, it already has everything you need for a small, basic application. It's still in alpha, but the API is taking shape. Some breaking changes will happen, but they should be minor, for the most part at least.

If you're interested in contributing, feel free to open an issue or a pull request.

You can also generally find me in the embedded graphics matrix channel if you have any questions.

Implemented and Planned Features

Basic Features

Advanced (and granular)

Something missing? Add an issue with the features you believe would be good.

Expected Breaking Changes

Why another GUI framework?

Actually, it's in some ways the first, at least in its very, very specific niche. The embedded-graphics environment is awesome, although fairly low-level. The goal of this library is to make creating simple to somewhat-complex GUIs trivially easy. There is nothing that does this, really, at least at the time of writing this library.

Sidenote: What is a Kolibri?

Kolibri is the german word for Hummingbird, which is a small bird that is very fast and agile. There is also an OS with a similar name (KolibriOS), for similar reasons: It is small and fast. This library is in no way associated with the KolibriOS project, but I do encourage you to check it out if you're interested.

What is this not?

Kolibri is not a high-end GUI framework. It is not meant to be used for creating very complicated or super nice-looking user interfaces. If that's something you're interested in, check out the rust bindings for lvgl or slint (not free for commercial use).

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.