Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Menu and ContextMenu events, allow for getting pointer info on open #6012

Closed
wants to merge 3 commits into from

Conversation

mat1jaczyyy
Copy link
Contributor

What does the pull request do?

Refactors ContextMenus and Menus based on #4443, and embeds position info for the Opened and Opening events on the ContextMenu for #5793.

What is the current behavior?

Open/close menu events are confusing. See #4443 for details why. It is also currently hard to tell where mouse cursor was when ContextMenu was opened.

What is the updated/expected behavior with this PR?

This PR drops the Closing event, and unifies naming across other events. On the ContextMenu, Opening and Opened events now have a GetPosition(IVisual? relativeTo) method which can be used to retrieve the position of the pointer at the time of the event opening.

How was the solution implemented (if it's not obvious)?

These were implemented after some discussion with @grokys, this does change the API in meaningful ways so I'm obviously still looking for feedback on whether this API change is justified (particularly, the dropping of the Closing event).

Checklist

Breaking changes

In addition to the removal of the redundant Closing event, Menu and ContextMenu event names were slightly changed.

Obsoletions / Deprecations

Fixed issues

Fixes #4443
Fixes #5793

@mat1jaczyyy mat1jaczyyy requested a review from grokys June 3, 2021 18:15
@mat1jaczyyy mat1jaczyyy self-assigned this Jun 3, 2021
@robloo
Copy link
Contributor

robloo commented Jun 3, 2021

There are usually always 4 events related to popups: Opening, Opened, Closing and Closed. I do not think it is a good idea to get rid of the Closing event.

In terms of a menu, the use cases for Closing are more rare. I'm sure there are cases where clicking on a menu item will cause a confirmation of some sort first which will delay closing of the menu. The Closing is really there to provide the option of manually controlling how the menu closes. Aside from the obvious API symmetry keeping this event, it seems like a bad idea to handicap future applications by removing it.

@robloo
Copy link
Contributor

robloo commented Jun 3, 2021

Also, don't forget FlyoutMenu which is part of the discussion (and arguably should replace ContextMenu).

public event EventHandler? Closed;
public event EventHandler<CancelEventArgs>? Closing;
public event EventHandler? Opened;
public event EventHandler? Opening;

/// <summary>
/// Defines the <see cref="Opened"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> OpenedEvent =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have Menu breaking changes, should we follow WPF/UWP APIs then?

In WPF there is no Menu.Opened/Closed event, which makes sense for me (do we really need them?).
But there is MenuItem.SubmenuOpenedEvent and MenuItem.SubmenuClosedEvent.

In case of UWP I don't see anything like that neither in MenuBar nor MenuBarItem nor MenuFlyoutSubItem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell from #4443, @grokys wanted to simplify and unify naming across controls rather than following WPF. I'm not sure if it's the way we should go with though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah not sure about Menu.Opened as the menu itself doesn't really "open" - it's its submenus that open. Having said that NativeMenu has an Opening event which maps to https://developer.apple.com/documentation/appkit/nsmenudelegate/1518156-menuwillopen?language=objc.

/// <summary>
/// Occurs when a <see cref="ContextMenu"/> is opened.
/// </summary>
public event EventHandler<ContextMenuEventArgs> Opened
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need to have this breaking change from ContextMenuOpening to Opened? Similarly to other events in this class.
I though we keep ContextMenu in Avalonia only because of historical reasons and compatibility with WPF?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That´s a good point. There is no reason to keep ContextMenu in my opinion if there is a breaking change from WPF anyway. It´s a good time to switch to MenuFlyout´s.

Copy link
Member

@grokys grokys Jun 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep ContextMenu, and migrate it to use native menus on relevant platforms as part of #3855. With that in mind, unifying the events is a good idea.

Copy link
Member

@maxkatz6 maxkatz6 Jun 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grokys ContextFlyout API is part of future native menu API.
It was discussed to be able tool write somethinf similar to:

<Control.ContextFlyout>
   <NativeMenuFlyout>
       <NativeMenuItem />
   </NativeMenuFlyout>
</Context.ContextFlyout>

Or

<Control.ContextFlyout>
   <MenuFlyout ShouldUseNativeMenu="True" >
       <MenuItem />
   </MenuFlyout>
</Context.ContextFlyout>

In any way existing Flyout API is more flexible comparing with ContextMenu.
Also it's not limited to right-click, and can be involed with public API on any control by any event.

/// Initializes a new instance of the ContextMenuEventArgs
/// class.
/// </summary>
public Point? GetPosition(IVisual? relativeTo)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it should be mentioned in the docs summary, that GetPosition returns null, when context menu was opened without pointer interaction?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Splitwirez
Copy link
Contributor

Would this allow one to programmatically tell whether a ContextMenu was opened via right-click or tap-and-hold? Because that could open up some...interesting possibilities.

(totally not referring to how some context menus in Windows 10 enlarge their items if opened via tap-and-hold, but keep them smaller if opened via right-click)

@mat1jaczyyy
Copy link
Contributor Author

@Splitwirez Lots of other info could be added to ContextMenuEventArgs in addition to GetPosition

@grokys
Copy link
Member

grokys commented Jun 7, 2021

Another thing to bear in mind is that WPF has FrameworkElement.ContextMenuOpening which is raised on the control that the menu is opening on: https://docs.microsoft.com/en-us/dotnet/api/system.windows.frameworkelement.contextmenuopening?view=net-5.0

This sounds like it might be a useful place to raise opening/closing events for context menus, particularly for menus which are shared between multiple controls. Does MenuFlyout have something similar?

@maxkatz6
Copy link
Member

maxkatz6 commented Jun 7, 2021

Does MenuFlyout have something similar?

With the event below developer can show anything when context flyout was requested. IMO it makes more sense.
https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.input.contextrequestedeventargs?view=winrt-18362

@grokys
Copy link
Member

grokys commented Jun 7, 2021

With the event below developer can show anything when context flyout was requested. IMO it makes more sense.
https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.input.contextrequestedeventargs?view=winrt-18362

Agreed. Would it be worth including this event in this PR?

@maxkatz6
Copy link
Member

maxkatz6 commented Jun 12, 2021

@grokys I will create separated PR with it and maybe with keyboard context menu without breaking changes. After that this PR can be rebased and merged into next big release with breaking changes.

Upd: started PR #6059

@maxkatz6
Copy link
Member

maxkatz6 commented Jan 7, 2022

Closing this PR for now. Would be great if anybody wants to pick it up.
#5793 is already possible, but it ContextMenu Opening event still lacks pointer information, should be easy to add.
#4443 is hard due to breaking change, when ContextMenu is already can be mostly replaced by better ContextFlyout.

@maxkatz6 maxkatz6 closed this Jan 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Open/close menu events are confusing Allow for getting pointer info when context menu is opening
5 participants