Implementing menus into hxWidgets

I’m going to be spending a great deal of time contributing to the hxWidgets library by @IanHarrigan1982 but I’m currently having trouble with implementing menus.

In my latest commit, I have been attempting to come up with some way to use the WxMenuItemRef signature the extern requires without coming across a stupid cannot convert from 'Dynamic' to 'wxMenuItem *' error.

https://github.com/tienery/hxWidgets-1/commit/05b49280334229585f65dbd1fddb05a445ed96cd

I personally think that the way the extern works is not going in this favour without otherwise writing some C++ in order to get this functionality to work properly.

The way the library is structured is that you create an extern for the object itself, and then another extern for the same object, but as a reference instead. So you have two classes like this:

@:include("wx/frame.h")
@:unreflective
@:native("wxFrame*")
extern class WxFrameRef extends WxFrame {
    @:native("new wxFrame")         public static function createInstance():WxFrameRef;
}

@:include("wx/frame.h")
@:unreflective
@:native("wxFrame")
extern class WxFrame extends WxWindow {
    @:native("Create")              public function create(parent:WxWindowRef, id:Int, title:ConstCharStar):Bool;
    @:native("CreateStatusBar")     public function createStatusBar():Void;
    @:native("SetStatusText")       public function setStatusText(text:ConstCharStar):Void;
    @:native("SetMenuBar")          public function setMenuBar(menuBar:WxMenuBarRef):Void;
}

This is of course a very simple implementation of a wrapper which could definitely do with a bit of work, because as I continue working on the menus, I cannot seem to implement a way in which to get the return signature and store it without a compilation error.

extern class WxMenu extends WxEvent {
    @:native("Append")          public function append(id:Int, item:ConstCharStar, helpString:ConstCharStar):WxMenuItemRef;
    @:native("AppendCheckItem") public function appendCheckItem(id:Int, item:ConstCharStar, help:ConstCharStar):WxMenuItemRef;
    @:native("AppendRadioItem") public function appendRadioItem(id:Int, item:ConstCharStar, help:ConstCharStar):WxMenuItemRef;
    @:native("AppendSeparator") public function appendSeparator():WxMenuItemRef;
    @:native("AppendSubMenu")   public function appendSubMenu(submenu:WxMenuRef, title:ConstCharStar, help:ConstCharStar):WxMenuItemRef;

I’m at the conundrum where the extern requires the return to be a reference to a MenuItem, but the way that Haxe works is that any extern use in a generated Haxe class is considered Dynamic until resolved at I believe runtime?

(I’m going to write a new reply because Discourse is extremely slow when writing long posts with embedded content it seems.)

Basically I need to store the reference of the return signature somewhere in a Haxe generated class without causing compilation errors. If you use an extern type it will complain you can’t assign a Dynamic type to it, even though the type signature you’re passing is exactly the same.

Example:

menuItem.setRef(menuRef.appendSubMenu(submenu.menuRef, title, help)); // errors saying it can't convert from 'Dynamic' to 'wxMenuItem *'
...

public function setRef(item:WxMenuItemRef) {
        _ref = item;
}

If you try using the MenuItem class by creating it first and assigning the ref variable directly, you end up with a function error something along the lines of this:

Cannot convert from 'null' to 'wxMenuItem *'

This error actually appears in Operators.h so assigning a value that hxcpp considers null despite the fact that the function signature is an extern is beyond me.

It’s just a huge headache at the moment, and I’m completely lost on what to do.

So I added menus to hxWidgets, not really sure about your implementation but i rolled out my own that fits with the wxWidgets framework and the way hxWidgets works / is setup and didnt run into any compilation problems at all. The code i added to the show case to use the new menu classes:

    var menuBar:MenuBar = new MenuBar();
    var file:Menu = new Menu();
    menuBar.append(file, "&File");
    var menuItem:MenuItem = new MenuItem(file, "Menu 1", hx.widgets.MenuItem.ItemKind.ITEM_CHECK);
    file.append(menuItem).check(true);
    file.append(new MenuItem(file, "Menu 2"));
    
    var menuItem:MenuItem = new MenuItem(file, "Menu 3", hx.widgets.MenuItem.ItemKind.ITEM_CHECK);
    menuItem.setBitmap(Bitmap.fromHaxeResource("inbox.png"));
    file.append(menuItem).check(true);
    
    frame.setMenuBar(menuBar);

And the result:

1 Like

Well, your implementation is different to mine, because I had the idea of implementing all the append options available in wxMenu. But nevertheless, you know your library better than I do :wink:

Still, it was worth the hassle because now at least I’ve learned something: Don’'t use extern classes with normal class function signatures, because it causes unwanted hxcpp errors.

You could create all the other function calls if you want of course, though i would say that the “main” function call is just to append a MenuItem to a Menu as that has all the functions in it to handle checkboxes, etc. That could also quite easily be implemented on the haxe wrapper classes of course (though it would cost nothing to expose the extern functions also).

I think the main issue you had with your code was extern class WxMenu extends WxEvent, i havent actually tried to reproduce the error using that class hierarchy as its simply not what the cpp classes have, but i think thats probably the root of the issues.

Cheers,
Ian

Oh, perhaps I was thinking of a different version? I was going by the current docs of wxWidgets: http://docs.wxwidgets.org/stable/classwx_menu.html

EvtHandler… not Event