andlabs/libui

Master issue: new menu API, with actions and keyboard shortcuts

andlabs opened this issue · 16 comments

The existing menu system is weird and will be hard to expand. OS X defines an entire interface of standard "actions" (NSResponder) with standard menu items and standard keyboard shortcuts, which will affect things as well. We'll need something different.

Originally I wasn't sure about what to do, but now I decided to go with an action-based system. You make an action object that has an event handler. The event handler would either contain the current control, the current window, or some combination of the two (or neither). There will be a set of standard actions, some of which can't be directly overridden; uiArea will provide an interface to handle these. Custom actions might be doable in the future; IDK.

Menus are now per-window. Most standard menu items are created by passing the standard actions into the menu functions. Standard menubar menus will also need to be made somehow. The OS X app menu will affect things here. You'll need to have an action in a menu to have the associated keyboard shortcut enabled (this is a limitation of OS X; TODO I could possibly work around it but IDK how — and then I would need to decide where the accelerator goes, in the action or the menu item). I also need to see if OS X automatically handles per-window menus or if I need to do it myself.

There should also be some way to determine whether an action is applicable in the present situation or not. This is how menu items are enabled or disabled. Again, OS X has the interfaces defined to do this (NSUserInterfaceValidation).

Other controls could also use actions for events somehow.

How to implement this on the other platforms isn't as certain, but the existing bugs on this issue have lots of notes; will need to refer to them.

Keyboard mnemonics should also be possible in menus, but on systems that support them.

Of course, I need to document what is platform-specific so app developers don't make features that are only accessible on some platforms because they are only accessible via one method that isn't available on all platforms.

This would also extend to right-click menus.

celyo commented

You can take a look at Lazarus menu system and actions. Lazarus is a cross platform and uses native gui toolkits to draw its elements on each platform (the same aproach as libui).

@celyo I wonder if anyone has tried writing C bindings to Lazarus.

So will there be a separate fork of the new Menu API, like with UTF support?

What do you mean by "UTF support"? Regardless, it would not be a separate fork (that is someone else cloning this repository to further development on it), but a branch (a separate timeline of commits that "branch" out from the main timeline and exist independently from that AND from all other branches until "merged" back, so developing features don't interrupt other features, or worse, other users, until they are finished).

Also late, but what is Lazarus's approach? (What classes do I look at?)

Ah yeah, I got the terminology mixed up, I meant "branch" instead.

That branch was not to add UTF-8 support to libui; it was to make all platforms use the same UTF-8 code, so they all react to invalid input the same predictable way. libui always supported UTF-8 (in fact, it should only work with UTF-8).

Nested menus would also be nice.

A smallish suggestion - changing the MenuItem creation method so that you can make a new MenuItem and then append it to menus would be more consistent with the rest of the functions that create new UI elements (e.g. uiNewButton). I'm not sure if this is too difficult to change for Windows though.

Whatever action I want to do would amount to a rewrite of the existing codebase anyway.

feer9 commented

Are these new features coming soon? I would really appreciate it

Are these new features coming soon? I would really appreciate it

I doubt it. He added to the Post-Alpha 5 milestone and just Alpha 5 seems to be in the distant future.

Not the distant future; I'm actively working on it, and really want to get things done by the end of the year.

I've already implemented a new events API, only to realize that it likely does not work well with menus, because events have a single source and many different handlers that aren't necessarily targets and that all are executed, but menu actions have multiple targets of which only one is actually targeted at a time. I'll need to think about it when I get to that point.

I've noticed even without the edit menu and command-v working to paste in text, you can still right click and select paste. Does anyone know if a scan gun "auto paste" feature would work without the command-v? i.e. a user in a warehouse could scan a barcode and the number would be pasted into the text field.

The OS X app menu will affect things here. You'll need to have an action in a menu to have the associated keyboard shortcut enabled

That's fine, but how? How can I enable Cmd+Q for Quit in the Application menu for example? Action onQuitClicked already defined in menu.m. See issue #501

Cheers,
bzt

I found the thread here indirectly via a google search, first from https://bleepcoder.com/libui/160938867/the-big-menu-issue (odd site, seems to aggregate github discussions), then the older issue here from 2016 #152 and finally the issue here.

Since I have not yet commented on it, here are a few opinions.

  • andlabs wondered about the "same feature set" on all platforms, e. g. on OSX in particular.

Personally I would be super-happy to say that libui is trying very hard to support the same feature
set on every main platform BUT to also allow for some platforms to use "differential features" if these
are supported or supportable.

Let me give you an example what i mean here.

GTK since version 3 has support for CSS, at the least a subset of CSS. I use this in
ruby-gtk3 just fine and it is super-pretty. I can customize all widgets, and I can even
re-use this (!) on by www-related websites. My local knowledge base is served
via HTML/CGI and sinatra, for instance. I no longer use hardcoded .cgi files but
instead use a separate file, usually a markdown .md file that is then read, evaluated
by my own custom webframework and then served by sinatra. This is super-easy
to set up (gem install sinatra; and gem install my gem). Once installed, just starting
sinatra works fine. Even oldschool .cgi files work fine too, with the very same codebase.
I love this.

So, since I can re-use CSS I'd love to have CSS support in libui, at the least for GTK.

But perhaps windows does not support CSS. Even in that case I'd much prefer CSS
to work on linux, and be "ok" with it when it does not work on windows. For me, on
windows, the main functionality is important. Ideally it should work great on windows
but I am fine if the functionality as such works. This is an area where libui does really
well. Getting GTK to work on windows is much more annoying ...

So, the TL;DR is that I think it would be ok to add "differential" support to individual
platforms, as long as the underlying goal (unified platform treatment) is retained.

The ideal state would be that we can support everything the same, but this also means
we would limit outselves in what we could support. So I think it would be nicer if we can
support some more feature sets on SOME platforms, and be ok with that as well.

Perhaps mark these in a special way and recommend people to not rely on them by
default - but if they really want to, they can use it.

This applies to CSS styling in my example, but also in the original thread by andlabs in
regards to menus. I'd love to have right-mouse menu work fine. If that works on linux
but not on windows that is still ok with me. I am using the ruby bindings anyway and
already modified them (kojix2 uses Fiddle::Pointer, and today I realized that I can
simply add modules to it, and then support an API like:

button = new_button('Hello world')
box.add(button1)

(For those who don't know, this is quite similar to how ruby-gtk works. We can use such methods like
.add() or .pack_start() on these widgets. pygobject in python works in a similar manner.)

andlabs wrote:

app developers don't make features that are only accessible on some platforms because they are
only accessible via one method that isn't available on all platforms.

I agree that this should be all documented, but I do not fully agree that it should be impossible. As
I explained above, I think there are fine use cases where more support is possible on some platforms
but not on others. For instance, if right clicking only works on linux and I know this, then I will write the
code in a way that windows users can still tap into the right-clicking behaviour. We can probably
easily work around this by just using MsgBox and adding whatever actions we need to do. Or in other
words, whether it is a right mouse click, or a button shown in the main UI, is IMO mostly a minor detail.
People can work around issues or restrictions and I think it would be better to allow people to do so.

The official libui can always aim for perfect 100% cross-OS support. I just don't think it needs to be in
a way that forbids custom modifications when some platforms support something but others don't.