MenuItem fails to be mapped between .fl and .rs (compiler error)
Giving this UI (src/ui.fl)
# data file for the Fltk User Interface Designer (fluid)
version 1.0308
header_name {.h}
code_name {.cxx}
class UserInterface {open
} {
Function {make_window()} {open
} {
Fl_Window {} {open
xywh {738 160 231 220} type Double visible
} {
Fl_Button but {
label {Click me}
xywh {66 67 95 45}
}
Fl_Menu_Bar {} {open
xywh {0 0 230 22}
} {
MenuItem m_menu {
label {Select me} selected
xywh {0 0 100 20}
}
}
}
}
}
When I try to used in src/main.rs:
use fltk::{prelude::*, *};
mod ui {
fl2rust_macro::include_ui!("src/ui.fl");
}
fn main() {
let a = app::App::default();
let mut ui = ui::UserInterface::make_window();
// this won't compile
// error[E0609]: no field `m_menu` on type `UserInterface`
// ui.m_menu.set_callback(|_b| println!("Menu clicked!"));
ui.but.set_callback(|_b| println!("Button clicked!"));
a.run().unwrap();
}
The Cargo.toml used was:
name = "bug_fl2rust"
version = "0.1.0"
edition = "2024"
[dependencies]
fl2rust-macro = "0.7.0"
fltk = "1.5.9"
fltk-rs uses MenuExt::add() to add menu itmes, as such you don't have access to them. The way to add callbacks to menu items is using the set_callback on a named menu bar. Then match paths:
ui.menubar.set_callback(|m| {
if let Ok(mpath) = m.item_pathname(None) {
match mpath.as_str() {
"Select me" => {},
_ => {}
}
}
});
Alternatively you can match on the mvalue()'s label.
AFAIK FLTK doesn't provide a simple way of creating a MenuItem and adding it to a menu bar. It requires aggregating MenuItem's into a array and setting the Fl_Menu_Bar::menu(array). It's error prone since you have to manually determine the submenues and separators. FLTK docs suggest using add() and insert() instead.
Okay, I can live with that although it would be great if something similar could be done to what the C++ generator does.
It generates something like:
class MW_UI {
public:
MW_UI();
// ....
static Fl_Menu_Item *m_menu; that can be used directly.
// ...
};
that can be used directly
I also remembered that the array has to be static and each submenu is sentinel terminated and the array itself sentinel terminated. It was a hassle to wrap in safe Rust: https://github.com/fltk-rs/fltk-rs/blob/e7048245acfaf1341da16d6cb4f8efd29ba625c3/fltk/src/menu.rs#L245
And a bigger hassle to use.
No problem, I can work it out as it is. Take it as an improvement for when you have time