Skip to content

Custom Widgets

George Atkinson edited this page Dec 19, 2020 · 2 revisions

Creating your own widgets

Creating your own widgets in tuix is quite easy. There are just 4 steps.

Step 1 - Defining the widget struct

The first step in creating a widget is to define a struct for it. You can have data inside the struct but this data will be local data.

pub struct MyAwesomeWidget {
  pub some_local_data: f32,
}

Step 2 - Implement the widget struct

Techinally this step is optional, but if you've got data inside your widget then it's just good practice.

impl MyAwesomeWidget {
  pub fn new() -> Self {
    MyAwesomeWidget {
      some_local_data: 42.0
    }
  }
}

Step 3 - Implement the BuildHandler trait

So this trait has one function, on_build(), which is called when a widget is built for the first time. The purpose of this function is to allow for inline properties to be set and for composition of widgets. For example, our brand new widget could contain a Button widget that gets created when an instance of MyAwesomeWidget is built.

The on_build function has 3 arguments, a mutable reference to self, a mutable reference to State, and an Entity id. The Enitity id is created by the application when the widget is built and allows us to get and set the properties of the widget within the State. The mutable reference allows us to access, and modify if we want, the local data in the widget instance.

You might have noticed already that the return type of the on_build function is an associated type. This is because the entity that is returned is the one you have access to when you call the build() function on a widget. However, if a widget is composed of multiple things we might need access to more than one entity. An example of this might be a tab container which has an entity for containing the tabs and an entity for containing the content, and in this case we might change Ret to (Entity, Entity) so we can return both. In this case though, we will just return the single entity which corresponds to the instance of our new widget.

impl BuildHandler for MyAwesomeWidget {
    type Ret = Entity;
    fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret {
        
        let some_button = Button::new().build(state, entity, |builder| builder);
        
        entity
    }
}

Step 4 - Implement the EventHandler trait

This is where all of the logic of the widget will go. The on_event function allows the widget to respond to events which are sent to it. Tuix uses dynamic dispatch for events so you need to downcast the event message to the type you want to respond to. In this case our widget is going to respond to WindowEvent so we call the is_type::<WindowEvent>() function on the event.

impl EventHandler for MyAwesomeWidget {
    fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) -> bool {
        if let Some(window_event) = event.message.downcast::<WindowEvent>() {
            match window_event {
                // Do Stuff
            }
        }
        false
    }
}