25th of October 2021 to 31st of October 2021

SixtyFPS UI Library

This week we worked primarily on a feature internal to the compiler we call "de-inlining".

The SixtyFPS compiler takes components in .60 files and generates C++ and Rust code. The following .60 code maps to this pseudo Rust code:

CountingButton := TouchArea {
    property <int> counter;
    Text {
        text: "pressed \{root.counter} times!";
    }
    clicked => {
        counter = counter + 1;
    }
}

App := Window {
    btn1 := CountingButton {
    }
    btn2 := CountingButton {
        y: 50px;
    }
}
    
// (note that this is all pseudo-code, for readability)
struct App {
    btn1_counter: Property<int>,
    btn1_touch_area: BuiltinTouchArea,
    btn1_label: BuiltinTextItem,
    btn2_counter: Property<int>,
    btn2_touch_area: BuiltinTouchArea,
    btn2_label: BuiltinTextITem
}

impl App {
    fn new() -> Self {
        self.btn1_label.text.set_binding(|| {
            format!("pressed {} times", self.btn1_counter.get())
        });
        self.btn1_touch_area.set_handler|| {
            self.btn1_counter.set(self.btn1_counter.get() + 1);
        });
        self.btn2_label.text.set_binding(|| {
            format!("pressed {} times", self.btn2_counter.get())
        });
        self.btn2_touch_area.set_handler|| {
            self.btn2_counter.set(self.btn2_counter.get() + 1);
        });
        self.btn2_touch_area.y.set(50);
    }
}

This generated code practically embeds all of CountingButton fields and binding code in the App struct. We call this inlining and it allows for nice optimizations and keeps the compiler simple. However a consequence of this inlining is that the resulting generated code becomes big and some parts of it are duplicated. A while ago we started the project of not inlining and this week we've merged the bulk of that into the mainline branch in order to finish it soon. The objective is to provide a more direct mapping between the components declared in .60 code and the generated Rust and C++ code, resulting in faster build times and smaller binaries. This is how the pseudo code should look like when not inlining:

struct CountingButton {
    counter: Property<int>,
    touch_area: BuiltinTouchArea,
    label: BuiltinTextItem
}

impl CountingButton {
    fn init(&self) {
        self.label.text.set_binding(|| {
            format!("pressed {} times", self.counter.get())
        });
        self.touch_area.set_handler|| {
            self.counter.set(self.counter.get() + 1);
        });
    }
}

struct App {
    btn1: CountingButton,
    btn2: CountingButton,
}

impl App {
    fn new() -> Self {
        self.btn1.init();
        self.btn2.init();
        self.btn2.touch_area.y.set(50);
    }
}

Almost all commits this week are related to this feature and the summary of individual commits did not make much sense. So this week's summary is a bit different than other weeks. Thanks for reading.

Statistics

61 patches were committed by 3 authors.

← Next : 1st of November 2021 to 7th of November 2021 | Previous : 18th of October 2021 to 24th of October 2021


Slint is a declarative GUI toolkit to build native user interfaces for desktop and embedded applications written in Rust, C++, JavaScript, and Python. Find more information at https://slint.dev/ or check out the source code at https://github.com/slint-ui/slint