1

I am trying to learn Rust and Fltk gui library. I see a small gui application example here which works perfectly. Following is the main fn:

fn main() {
    let     a    = app::App::default().with_scheme(app::Scheme::Gtk);
    let mut win  = window::Window::default().with_size(500, 300);
    let mut form = Form::default();
        
    form.register_default_callback();
    win.end();
    win.make_resizable(true);
    win.show();
    win.resize_callback(move |_, _, _, w, h| form.resize(0, 0, w, h));

    a.run().unwrap();
}

I see here that the form Form is not explicitly added to the win window.

The Form is a structure defined in upper part of the program:

struct Form {
    grid      : Grid,
    name      : input::Input,
    age       : input::IntInput,
    occupation: input::Input,
    btn       : button::Button,
}

impl Form {

    pub fn default() -> Self {
        let mut grid = Grid::default_fill();
        grid.set_layout(10, 5); // construct a new grid

        let name       = input::Input::default();
        let age        = input::IntInput::default();
        let occupation = input::Input::default();
        let btn        = button::Button::default().with_label("Submit");

        let mut g = Self {
            grid,
            name,
            age,
            occupation,
            btn,
        };
        g.fill();
        g
    }

    fn fill(&mut self) {
        let grid = &mut self.grid;
        grid.debug(false); // set to true to see cell outlines
        
        let mut title = frame::Frame::default().with_label("Employee Form");
        title.set_frame(enums::FrameType::FlatBox);
        title.set_color(enums::Color::Red);
        title.set_label_color(enums::Color::White);
        grid.insert(
            // insert widgets
            &mut title, 0, 1..4
        );

        grid.insert(&mut frame::Frame::default().with_label("Name"), 2, 1);
        grid.insert(&mut self.name, 2, 3);

        grid.insert(&mut frame::Frame::default().with_label("Age"), 4, 1);
        grid.insert(&mut self.age, 4, 3);

        grid.insert(&mut frame::Frame::default().with_label("Occupation"), 6, 1);
        grid.insert(&mut self.occupation, 6, 3);

        grid.insert(&mut self.btn, 8, 2);
    }

    fn register_default_callback(&mut self) {
        self.btn.set_callback({
            let name       = self.name.clone();
            let age        = self.age.clone();
            let occupation = self.occupation.clone();
            move |_| {
                println!("Name: {}", name.value());
                println!("Age: {}", age.value());
                println!("Occupation: {}", occupation.value());
            }
        });
    }

    pub fn resize(&mut self, x: i32, y: i32, w: i32, h: i32) {
        self.grid.resize(x, y, w, h); // determine how it's resized
    }
}

Only line which has both win and form is following:

win.resize_callback(move |_, _, _, w, h| form.resize(0, 0, w, h));

However, the application works even when this line is removed.

How does the Form appear automatically in the window?

rnso
  • 23,686
  • 25
  • 112
  • 234
  • The `Form` is a structure defined in upper part of the program. I have clarified this in my question above. – rnso Apr 14 '23 at 01:48

2 Answers2

1

This is because Form isn't actually a widget being added to the window, it's calling Grid::default_fill inside of Form::default, which then adds it to the window.

eten
  • 803
  • 3
  • 14
1

It's because of the way FLTK works. When you create a container (like win) then all widgets that are created afterwards automatically get added to this container until you call its end method.

See the book for more details on Group widgets.

Jmb
  • 18,893
  • 2
  • 28
  • 55
  • That sounds like the worst possible way to design an API - I'm assuming it works by using thread-local-storage to hold a globally-accessible reference to whatever the current ambient context or ambient subject is... or is it not even thread-safe? – Dai Apr 14 '23 at 13:28
  • @Dai I agree about the poor design, but that's the way the underlying C++ library works. And I don't know if it's thread-safe, but it probably isn't (most GUI libraries don't like to have widgets changed from multiple threads). – Jmb Apr 14 '23 at 13:34
  • @Dai also remember that FLTK is over 25 years old (the first commit dates back to october 1998 and that imported 61_000 lines of code in 458 files so FLTK is obviously much older), and what seems a bad idea today may have been seen differently at the time. – Jmb Apr 14 '23 at 13:38