Automating User Interfaces + Gooey Updates

Tonight I uploaded a readme into the examples folder for Gooey. The animated PNGs embedded were generated using a new Headless renderer and accompanying Recorder type. I’m extremely excited at the prospects here. For example, let’s look at the basic example:

let mut headless = Counter::headless();
let mut recorder = headless.begin_recording(Size2D::new(320, 240), theme, true, 30);
recorder.set_cursor(Point2D::new(100., 200.));
recorder.render_frame(Duration::from_millis(100)).await?;
recorder
    .move_cursor_to(Point2D::new(160., 130.), Duration::from_millis(300))
    .await?;
recorder.pause(Duration::from_millis(250));
recorder.left_click().await?;

assert_eq!(
    "1",
    &recorder
        .map_root_widget(|component: &mut Component<Counter>, context| {
            component
                .map_widget(
                    &CounterWidgets::Button,
                    &context,
                    |button: &Button, _context| button.label().to_owned(),
                )
                .unwrap()
        })
        .unwrap()
);

recorder
    .move_cursor_to(Point2D::new(200., 180.), Duration::from_millis(300))
    .await?;
recorder.pause(Duration::from_millis(1000));

recorder.save_apng(harness::snapshot_path(
    "basic",
    &format!("Demo-{:?}.png", theme),
)?)?;

This code not only generates an animation showing off the example, it also operates as a test. To me this is incredibly exciting: I now have the basics of how to build end-to-end tests, and Gooey users can use it as well.

Currently this is only supported using the frontend-kludgine feature flag. I believe we can add support for frontend-browser using a headless chrome instance, but it will be something done much further down the road.

What else is new in Gooey?

This past week, I resurrected Kludgine’s text wrapping code in order to add text wrapping support to the Label widget. The code supports styled text wrapping, but the Label itself only supports a single style currently. This new renderer-based ecosystem is something I have grand visions for: a portable system of rendering functionality that is all built atop a single Renderer trait.

After that, I added a Checkbox widget. I thought it would be straightforward, but the lengths you must go to in CSS to support accessibility and custom styling properly was a lot more than I expected.

What’s next for Gooey

Our sights are focused on a goal we’ve had since February: getting Cosmic Verge up and running on this new architecture. One of the stops along the way is being able to support enough user interface to allow a user to log in or create an account. Because user interfaces are so critical, we are wanting to make sure we have a solid foundation before focusing too much on the game.

@dAxpeDDa is wrapping up some Custodian related work and will be tackling a Grid widget soon. In our experience, a majority of interface design is easily accomplished using a grid layout. This widget will compliment the custom Layout widget we currently have.

Up next for me is a first pass at a single-line text entry widget. This is also something I had implemented in Kludgine before, but because it also requires focus-handling, it’s going to be a fair amount of work.

But, there are also considerations on how to build full applications. So far, much of Gooey has been focused on the basics. To create maintainable applications, we need to also focus on the types of widgets that help compose complex interfaces. For example, tab views, navigation controllers, toolbars, dialogs, toasts, and more.

After this past week, I’m looking forward to actually using this framework to build apps. Hopefully soon!