fl2rust icon indicating copy to clipboard operation
fl2rust copied to clipboard

MenuItem fails to be mapped between .fl and .rs (compiler error)

Open diegoefe opened this issue 5 months ago • 4 comments

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"

diegoefe avatar Jun 25 '25 10:06 diegoefe

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.

MoAlyousef avatar Jun 25 '25 12:06 MoAlyousef

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

diegoefe avatar Jun 25 '25 13:06 diegoefe

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.

MoAlyousef avatar Jun 25 '25 15:06 MoAlyousef

No problem, I can work it out as it is. Take it as an improvement for when you have time

diegoefe avatar Jun 25 '25 17:06 diegoefe