question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Description

Provide a cross platform API to allow the specification of a MenuBar for desktop applications.

Public API Changes

Option 1: Just Copy WinUI structures API

IMenuBarElement

This is used to attribute a view indicating that it has a MenuBar element that needs to be taken into consideration

public interface IMenuBarElement
{
	IMenuBar? MenuBar { get; }
}

IMenuBar

Top Level container.

Alternative option here would be to use the existing Menu type.

public interface IMenuBar : IList<IMenuBarItem>, IElement
{
}

IMenuBarItem

Used to describe each primary menu inside the MenuBar (File, edit, etc…)

public interface IMenuBarItem : IList<IMenuFlyoutItemBase>, IElement
{
	string Text { get; }
        MenuBarItemKey Key { get: }
}

MenuBarItemKey

Used to map a MenuBarItem to a system menu

public enum MenuBarItemKey
{
    File, Edit, View, //The rest of the default menus in catalyst
}

IMenuFlyoutItem

Describes an item that the user will click on to trigger behavior

public interface IMenuFlyoutItem : IMenuFlyoutItemBase
{
	string Text { get; }
	Action Clicked { get; }
}

IMenuFlyoutSubItem

Used to create submenus

public interface IMenuFlyoutSubItem : IMenuFlyoutItemBase, IList<IMenuFlyoutItemBase>
{
	string Text { get; }
        short Position { get; } // ?? This can be used to insert sub menus at different points on catalyst
}

Platform Mappings

  • WinUI : 1:1
  • Catalyst
    • MenuBar => UIMenuBuilder
    • MenuBarItem => UIMenu
    • MenuFlyoutItem => UIAction/UICommand
    • MenuFlyoutSubItem => UIMenu

Considerations

We currently have a Menu API that is only used on MacOS. This API can be used as an attached property on every single Element. On MacOS this would become a context menu for Elements and the main menu when it was set on the Application. Do we want to keep this one type for both scenarios? On WinUI the FlyoutMenu's all reuse the MenuFlyoutItem types but then use MenuFlyout as the parent element vs MenuBarItem/MenuBar

Catalyst has a default menu that it displays, so the process of interacting with the menu is more modification based instead of just creating the menu like on WinUI. I’ve added a few APIs to help with this but we could do something more in v2. Just having the handlers will give users a valuable extension point to make modifications. They can just tap into the MenuBarHandler and from there issue commands to the builder.

Intended Use-Case

https://developer.apple.com/documentation/uikit/uicommand/adding_menus_and_shortcuts_to_the_menu_bar_and_user_interface https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.controls.menubar?view=winui-3.0

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:14
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
profix898commented, Feb 13, 2022

I checked your implementation and it mostly fits my intuition (what is to say that I was able to grasp the structure right away), which I think is usually a good sign. That said, here are a few comments on the current design and naming.

  1. General API design

We currently have a Menu API that is only used on MacOS. This API can be used as an attached property on every single Element. On MacOS this would become a context menu for Elements and the main menu when it was set on the Application."

My vote is for a unification of Menu/MenuBar and MenuItem/MenuFlyoutItem (and related items).

There are two aspect to this IMO.

a) You would probably want a context menu that can be added to other elements on WinUI as well. Right now (correct me if I’m wrong), MAUI only has context menu for ListView items. Not a general concept of context menu (for other views). In WinUI there is the ‘ContextFlyout’ property on ‘UIElement’ (https://docs.microsoft.com/de-de/uwp/api/windows.ui.xaml.uielement.contextflyout), which can be used to attach a context menu to any UIElement. So, I guess this is conceptionally similar to macOS.

b) We should have one unified way of building a window-/application-level menu in MAUI. Not a type that is specific to macOS.

I understand that with Catalyst you have a default menu. But I guess for a first iteration, you could “simply” merge the MAUI menu with the pre-existing default menu (by means of using the MenuBarItemKey flag and Position property, as you suggested in your API design, although the latter might need more thinking). At this point, it would probably require some custom logic to “apply” properties, commands, etc. to the existing menu items (e.g. in File menu).

I also think that the unified design should be based on your new proposal. The current/old Menu in MAUI has this (weird) structure with _menu and _items as two separate collections. So it’s used as a container (= MenuBar) and/or as a top-level menu (= MenuBarItem, e.g. File). For me this contradicts a self-documenting/explaining API design (and probably single-purpose rule). One potential reason is that its top-level menu was used (as item list) to populate the navigation menu for flyout pages (Hamburger menu).

  1. Considering that menus are found in different areas of an app, I’m not sure about the current naming schema. I would suggest to rename a few things, e.g.:

MenuBar -> MenuBar is Ok

MenuBarItem -> Menu unless you build a window-/app-level menu(bar), this will be the root item/container for context menus or simple single-level menus (e.g. Hamburger menu). For that reason, MenuBar in its name is misleading as it can be used separate of MenuBar as well.

MenuFlyoutItem -> MenuItem MenuFlyoutSubItem -> MenuSubMenu(Item) Why do you have both? At least on Windows (WinForm, WPF, etc.) you can have a Click event for a submenu as well. So the only difference is that a submenu contains other menu items. Other than that it has all the same properties: text, icon, accelerator, (click) events. My guess is that having two separate types makes the handler mapping unique in MAUI, right? In that case, you could still make MenuFlyoutSubItem derive from MenuFlyoutItem, not?

  1. There are some features missing in your prototype (accelerators) as well as additional menu item types (toggle/checked, radio select, …) Just so we keep track … 😉
0reactions
PureWeencommented, Feb 17, 2022

Alright started wiring up the Catalyst parts and checked that all in. There’s some interesting parts we need to figure out with Selectors but otherwise it’s mostly working

Read more comments on GitHub >

github_iconTop Results From Across the Web

What is a Menu Bar?
A menu bar is a thin, horizontal bar containing the labels of menus in a GUI. The menu bar provides the user with...
Read more >
Menu and Menubar Pattern | APG | WAI
A menu that is visually persistent is a menubar. A menubar is typically horizontal and is often used to create a menu bar...
Read more >
What's in the menu bar on Mac?
The menu bar runs along the top of the screen on your Mac. Use the menus and icons in the menu bar to...
Read more >
MenuBar (JavaFX 8)
A MenuBar control traditionally is placed at the very top of the user interface, and embedded within it are Menus . To add...
Read more >
Menu bar
A menu bar is a graphical control element which contains drop-down menus. Menu bar of Mozilla Firefox. The menu bar's purpose is to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found