andlabs / libui

Simple and portable (but not inflexible) GUI library in C that uses the native GUI technologies of each platform it supports.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

The big menu issue

andlabs opened this issue · comments

The current menu API is a huge kludge right now.

  • Only one menubar for the entire program; no way to make right-click menus
  • Menus and menu items can only be created until the first uiWindow is created
  • No way to specify accelerators
  • No way to specify mnemonics
  • Predefined About, Preferences, and Quit items for OS X, the last having a predefined handler due to the Dock icon's Quit item being nonprogrammable — and those aren't enough

OS X PROBLEMS

Everything is an informal protocol.

Many of the standard menu items, most notably in the Edit menu, work by sending a predefined selector, such as cut:, to the first responder. Things like NSTextField and NSTextView already implement all of this; we can do this in uiArea with a bunch of extensions to uiAreaHandler.

But all those items would need to be made predefined menu items, such as uiMenuAppendCutItem(). Maybe a macro would be better.

Also keyboard accelerators only work if tied to a menu item. Command+C for copy has to be on the Copy item. (Corollary: programmable accelerators would allow us to override these conventions. Should we? Right now the Application Menu is hardcoded to do Command+, be Preferences and Command+Q to be Quit, and Command+(Option+)H for the various Hide options.)

I want to eventually support the Document-Based Application framework. This might add a bunch more predefined menu items.

Unsure about:

  • File > Close is defaulted to performClose:, a NSWindow method which simulates clicking the Close button
  • Find/Replace all involve panels
  • Spelling/Grammar do too, plus we explicitly disable all that anyway
    • Substitutions too
  • the Fonts, Format, and Text menus operate antithetically to how we operate; in fact, so did the Font dialog (that's why we have uiFontButton)
    • on GTK+ and Windows, the font dialog is a MODAL thing
    • and again, all these items expect to use standard NSText selectors to do their thing, otherwise they would only work for our views
    • Text menu involves rulers, which we also don't support because only OS X provides them
  • Window menu:
    • fullscreen is NOT part of this menu (it's part of the View menu, if any) (and it also uses a NSWindow selector)
    • we need to take care not to put dialogs here on other platforms
    • in fact, on other platforms we have to do this ourselves (Windows does automate the process for its MDI but only for its MDI and its MDI is long deprecated)
  • Help: unlike other platforms, application name should be in the Help item name

There are also canonical text editing shortcuts handled by the text system. Relevant to the uiArea text discussion as well.

Finally, there's the global menubar. If we have per-window menus, we would need to watch when the key window changes to change the menubar...

GTK+ ISSUES

I'm not sure how copy/paste/etc. work. Is it keybinding signals or GtkAccelGroup? Or is it gtk_window_add_mnemonic()?

WINDOWS ISSUES

There is no standard editing interface, but there are some editing messages like WM_UNDO and WM_COPY. Unfortunately, the Edit control also provides its own which it prefers under some circumstances. Unfortunately unfortunately, there's nothing like WM_CANUNDO (as far as I know).

So we would need an interface for cut/copy/paste/etc. somehow.

Microsoft recommends against using Preferences, instead suggesting Options

IIRC can't have a hard tab in a menu label; that's how keyboard shortcuts work

So I'm not sure what to do. What kind of API would be better? It shouldn't be purely declarative as opposed to functional (declarative APIs can be written on top of non-declarative APIs easily, but not the other way around).

WINDOWS ISSUES

There is no standard editing interface, but there are some editing messages like WM_UNDO and WM_COPY. Unfortunately, the Edit control also provides its own which it prefers under some circumstances. Unfortunately unfortunately, there's nothing like WM_CANUNDO (as far as I know).

I think the messages you're looking for on Windows for the Edit Control are EM_UNDO and EM_CANUNDO.

Yes, but that's only for the edit control. I'd have to monitor what the currently focused control is to see which messages I need to send.

Something else to consider is the native "Quit" vs "Exit" phrasing that each platform uses. Might be nice to have a function that sets up a default set of menus for that platform, and one could provide flags for what menus they may want. For example an Exit/Quit menu, a Preference/Settings/Options menu, a Help menu, an Edit menu, etc.

Part of the problem for OS X is that the Cocoa framework is very much built upon XIB files and Xcode... it isn't designed to be wrapped by an API such as libui, and this is why most Mac apps that aren't programmed in Objective-C/Swift tend to have little quirks that "native" apps don't. I don't really see how to proceed here in a way that also makes sense on other platforms; on one of my applications I ended up scrapping using libui for the Mac version (I'm still using it for Windows and OS X) and just using plain Cocoa instead.

commented

Just a proposal from my side (I'm not a C guy but I wanted such a library for years - to be easily ported to almost every language). Why don't you take some ideas from wxWidgets or even Lazarus LCL? Both libraries are wrappers and have implementations for all 3 platform that you need. In addit ion they have working menu system + forms + dialogs + all of the elementary controls. Just observer their implementation and may be you can take some ideas. Tahnk you for the amazing job!

Why not let applications detect the OS and use different phrasing/controls on each?

No. OS detection is evil, that would defeat the goal of libui. If you want different controls on each platform, just use directly the native libraries.

Then in that case we should just not do anything special regarding macOS's special menus and use the same controls that we'd use on windows or gtk.

@PaulBGD @emersion As I pointed out in this comment above, the Mac's user experience is not meant to be wrapped in a separate framework. There really is no good cross-platform way to handle menus on OS X. Either you add lots of new code to handle OS X (which can't be re-used on other platforms) or you settle for a sub-par user experience. That, unfortunately, is the reality.

Which is why I was suggesting allowing applications to handle macOS.

Would it make sense to create a new library (outside of libui) for macOS-specificities? like libui-macos to be used in conjunction with this library. For apps that want want/need that native feel.

What would that library do?

It would offer the supplemental macOS-specific APIs that are unwanted in
this lib.
On Fri, Jun 24, 2016 at 8:29 PM Pietro Gagliardi notifications@github.com
wrote:

What would that library do?


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#152 (comment), or mute
the thread
https://github.com/notifications/unsubscribe/AACpPfGDr2MNXcu_tzGZH34ABPhLSUMrks5qPJKPgaJpZM4I4k10
.

I think the suggestion to look at wxWidgets is a good one. I've used it on OSX and Windows and it doesn't hve a "subpar" feeling for either platform. It is certainly possible to build menus in code and have a common api in libui that translates to the appropriate menus on each platform

I'd say, provide a method to create menu items in general form and implement platform conventions in a separate component (maybe declarative). uiMenuAppendCutItem can be a building block in the conventions layer. We probably will need quite a number of such high-level conventions like OK/Cancel button placement, client area in a window with menu etc.

Replaced with #321.