This week in Gooey: Navigator and Canvas

I’ve made a lot of progress on Gooey since the last update, and it seemed like it was a good time to reflect on the progress. Since the last update, I’ve been focused on trying to get Gooey ready to build more complicated applications.

Multi-screen applications

The first project I tackled was a Navigator widget:

Navigator Demo

This widget manages a back stack of visited locations and allows navigating through your application using a Location trait implementer. Eventually this control will support interacting with the browser’s back stack as well.

To make this widget support, I had to implement a lot of missing support for adding/removing widgets and ensuring all resources are cleaned up properly. For example, modifying CSS rules on the fly as widgets are added and removed was trickier than anticipated.

Implementing a Canvas widget

As we get closer to having all the basic components necessary to rebuild our existing Cosmic Verge prototype, I grew excited at the idea of getting cross-platform drawing working inside of Gooey.

As part of this, I also began implementing asset handling – specifically Gooey now can load images to be used in a Renderer. A widget for displaying images will be coming soon – the focus on this work was to tackle what I considered the toughest problems. I believe getting the rest of image handling done at this stage will be mostly straightforward, but there’s still a lot of work left.

The above screenshot shows this code rendering in both a browser and a native app:

// When creating the app:
Component::new(
    Basic {
        image: Image::from(Asset::build().path(vec!["rolls.jpg"]).finish()),
    },
    storage,
)

// Inside of a Component Behavior:
fn build_content(
    &mut self,
    builder: <Self::Content as Content<Self>>::Builder,
    _events: &EventMapper<Self>,
) -> StyledWidget<Self::Content> {
    let image = self.image.clone();
    builder
        .on_render(move |renderer: CanvasRenderer| {
            renderer.fill_rect(&renderer.bounds().inflate(-64., -64.), Color::RED);
            renderer.draw_image(&image, Point2D::new(128., 128.));
        })
        .finish()
}

The full example can be seen here. One special note: the Canvas widget is the first widget that is not inside of the gooey-widgets crate. The project’s readme talks about this design decision.

In addition to adding the Canvas, the above snippet shows off some of the improved ergonomics in the Renderer API. The trait previously was only used when rendering controls, and all of the calls relied on the Style object. Now the Renderer implementations don’t have to handle Style directly, and instead interact directly with strongly-defined types. If a Renderer wanted to support some custom style components, it can still provide its own implementation of the style-based methods.

Lastly, I added all the CSS color constants and made the internal color handling use const fn in many locations.

Updated to wgpu 0.9

In the process of exploring how I had implemented some of the shape drawing code, I found myself looking at easygpu. Since I had it open, I decided to attempt updating to the latest version of wgpu.

To my surprise, none of the breaking changes in this round affected easygpu, easygpu-lyon, or Kludgine. I didn’t take time to attempt running Kludgine on wasm yet, and it’s very low on my list of curiosities. For now, Cosmic Verge will be using the Canvas to render graphics in the browser.

What’s up next?

I’m not exactly done with Canvas or Images, but my goal was only to get canvas rendering working so that I was ready to try getting Cosmic Verge running again. Now that I’ve done that, I find myself getting pulled back to working on a text input widget.

As I see it, once I have a text input widget, I have all the necessary widgets to create a basic sign up/log in form and render the previous game.

To recap, since March we’ve built this prototype user interface library as well as BonsaiDb which is aiming to replace PostgreSQL and Redis from our deployment stack. So, to finally see the proverbial light at the end of the tunnel of being able to tie Gooey and BonsaiDb together into Cosmic Verge:

To say that I’m excited is an understatement. While there’s still a lot of work left, it’s rewarding to finally be putting it all together.