picoe / Eto

Cross platform GUI framework for desktop and mobile applications in .NET
Other
3.57k stars 325 forks source link

Add an option to avoid closing context menu on interact #1647

Open Sejsel opened 4 years ago

Sejsel commented 4 years ago

I would very much use a new property named something akin to CloseOnInteract in the ContextMenu. It should default to true to match the current behavior, but setting it to false would result in the context menu not being closed immediately after interacting with a menu item.

This would make it possible to change multiple checkbox values in a ContextMenu which is something I would find useful for making filters as having to open the context menu again after each checkbox click is rather tenuous.

If I am reading correctly, the option would result in the following lines not being called: https://github.com/picoe/Eto/blob/develop/src/Eto.Gtk/Forms/Menu/ContextMenuHandler.cs#L89 https://github.com/picoe/Eto/blob/develop/src/Eto.Wpf/Forms/Menu/MenuItemHandler.cs#L163 https://github.com/picoe/Eto/blob/develop/src/Eto.WinForms/Forms/Menu/ContextMenuHandler.cs#L25

Can't find the equivalent for Eto.Mac, not even sure if it closes automatically on the platform, I don't have any way to test it.

cwensley commented 4 years ago

This can't be done on macOS afaik. Thanks for the suggestion, but I don't think this is doable.

Sejsel commented 4 years ago

Ah, that's a shame, was not aware of that. Do you happen to know if this can be done easily by making a custom platform control? I have attempted it, but it looks like I would pretty much have to duplicate all code related to the context menu, didn't figure out how override just one method with the API it has.

cwensley commented 4 years ago

Yes you can create a custom platform control. If you make it a subclass of the ContextMenu and its associated handler(s) for each platform you won't have to reimplement everything.

For example:

[Handler(typeof(IHandler))]
public class MyContextMenu : ContextMenu
{
  new IHandler Handler => (IHandler)base.Handler;

  public bool CloseOnInteract
  {
    get => Handler.CloseOnInteract;
    set => Handler.CloseOnInteract = value;
  }

  public new interface IHandler : ContextMenu.IHandler
  {
    bool CloseOnInteract { get; set; }
  }
}

Then, for example WPF:

[assembly: Eto.ExportHandler(typeof(MyContextMenu.IHandler), typeof(MyContextMenuHandler))]

public class MyContextMenuHandler : Eto.Wpf.Forms.Menu.ContextMenuHandler
{
  public bool CloseOnInteract
  {
    get { /* todo */ }
    set { /* todo */ }
  }
}

Hope this helps!