andlabs / libui

Simple and portable (but not inflexible) GUI library in C that uses the native GUI technologies of each platform it supports.
Other
10.73k stars 614 forks source link

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

Open andlabs opened 6 years ago

andlabs commented 6 years ago

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 6 years ago

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).

DemiMarie commented 6 years ago

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

hanyuone commented 6 years ago

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

andlabs commented 6 years ago

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?)

hanyuone commented 6 years ago

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

andlabs commented 6 years ago

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).

mischnic commented 6 years ago

Nested menus would also be nice.

hanyuone commented 6 years ago

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.

andlabs commented 6 years ago

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

andlabs commented 6 years ago

Notes on keyboard shortcuts: https://www.youtube.com/watch?v=g8FT2F2XWmo

feer9 commented 5 years ago

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

agillgilla commented 5 years ago

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.

andlabs commented 5 years ago

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.

andrewarrow commented 5 years ago

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.

bztsrc commented 4 years ago

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

rubyFeedback commented 3 years ago

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 https://github.com/andlabs/libui/issues/152 and finally the issue here.

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

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.