using System;
using System.Globalization;
+using System.Linq;
using AppKit;
using CoreGraphics;
using Foundation;
{
ObjCRuntime.Runtime.MarshalManagedException += (sender, args) =>
{
- Console.WriteLine(args.Exception.ToString());
+ Console.WriteLine(args.Exception);
};
var style = NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled;
get { return _window; }
}
+
public override void DidFinishLaunching(NSNotification notification)
{
Forms.Init();
FormsMaps.Init();
var app = new App();
+ SetupMenu(app);
+
// When the native control gallery loads up, it'll let us know so we can add the nested native controls
MessagingCenter.Subscribe<NestedNativeControlGalleryPage>(this, NestedNativeControlGalleryPage.ReadyForNativeControlsMessage, AddNativeControls);
MessagingCenter.Subscribe<Bugzilla40911>(this, Bugzilla40911.ReadyToSetUp40911Test, SetUp40911Test);
base.DidFinishLaunching(notification);
}
+ void SetupMenu(Application app)
+ {
+ NativeMenuItemCreator = (menuItem) =>
+ {
+ if (menuItem is SeparatorMenuItem)
+ {
+ return NSMenuItem.SeparatorItem;
+ }
+
+ var nsMenuItem = new NSMenuItem { Title = menuItem.Text };
+ if (menuItem.Text == "Small icons")
+ {
+ nsMenuItem.State = NSCellStateValue.On;
+ nsMenuItem.Activated += CheckableNsMenuItem_Activated;
+ }
+
+ return nsMenuItem;
+ };
+
+ var menu = new Menu();
+
+ var appMenu = new Menu();
+
+ appMenu.Items.Add(new MenuItem { Text = "App menu test" });
+ menu.Add(appMenu);
+
+ var fileMenu = new Menu { Text = "File" };
+ fileMenu.Items.Add(new MenuItem { Text = "New" });
+ fileMenu.Items.Add(new MenuItem { Text = "Open" });
+ menu.Add(fileMenu);
+
+ var viewMenu = new Menu { Text = "View" };
+ var smallIconsMenuItem = new MenuItem { Text = "Small icons" };
+ smallIconsMenuItem.Clicked += CheckableMenuItem_Clicked;
+ viewMenu.Items.Add(smallIconsMenuItem);
+ viewMenu.Items.Add(new MenuItem { Text = "Large icons" });
+ viewMenu.Items.Add(new SeparatorMenuItem());
+ viewMenu.Items.Add(new MenuItem { Text = "List", IsEnabled = false });
+ viewMenu.Items.Add(new MenuItem { Text = "Details" });
+ menu.Add(viewMenu);
+
+ Element.SetMenu(app, menu);
+
+ void CheckableNsMenuItem_Activated(object sender, EventArgs e)
+ {
+ // switch state for checkable menu item
+ var nsMenuItem = sender as NSMenuItem;
+ nsMenuItem.State = nsMenuItem.State == NSCellStateValue.On ? NSCellStateValue.Off : NSCellStateValue.On;
+ }
+
+ void CheckableMenuItem_Clicked(object sender, EventArgs e)
+ {
+ var menuItem = sender as MenuItem;
+ var alert = new NSAlert { MessageText = $"{menuItem.Text} has been clicked!" };
+ alert.RunModal();
+ }
+ }
+
+ protected override void SetupMainAppMenu(NSMenu nativeMenu)
+ {
+ base.SetupMainAppMenu(nativeMenu);
+
+ // reorder menu items - it can be needed if we add submenus as they are added after simple items
+ var appMenu = nativeMenu.ItemAt(0);
+ var testMenuItem = appMenu.Submenu.Items.Last();
+ appMenu.Submenu.RemoveItem(testMenuItem);
+ appMenu.Submenu.InsertItem(testMenuItem, 0);
+ }
+
void AddNativeControls(NestedNativeControlGalleryPage page)
{
if (page.NativeControlsAdded)
--- /dev/null
+
+namespace Xamarin.Forms.ControlGallery.MacOS
+{
+ /// <summary>
+ /// Represents a separator menu item
+ /// </summary>
+ public class SeparatorMenuItem : MenuItem
+ {
+ }
+}
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Compile Include="PlatformSpecificCoreGalleryFactory.cs" />
<Compile Include="RegistrarValidationService.cs" />
<Compile Include="SampleNativeControl.cs" />
+ <Compile Include="SeparatorMenuItem.cs" />
<Compile Include="..\Xamarin.Forms.Controls\GalleryPages\OpenGLGalleries\AdvancedOpenGLGallery.cs">
<Link>GalleryPages\AdvancedOpenGLGallery.cs</Link>
</Compile>
{
internal static class NSMenuExtensions
{
- public static NSMenu ToNSMenu(this Menu menus, NSMenu nsMenu = null)
+ public static NSMenu ToNSMenu(this Menu menus, NSMenu nsMenu = null, Func<MenuItem, NSMenuItem> menuItemCreator = null)
{
if (nsMenu == null)
nsMenu = new NSMenu(menus.Text ?? "");
+ nsMenu.AutoEnablesItems = false;
+
foreach (var menu in menus)
{
- var menuItem = new NSMenuItem(menu.Text ?? "");
- var subMenu = new NSMenu(menu.Text ?? "");
- menuItem.Submenu = subMenu;
+ NSMenuItem menuItem = null;
+ NSMenu subMenu = null;
+ if (string.IsNullOrEmpty(menu.Text)) // handle menu with empty Text as the application menu
+ {
+ menuItem = nsMenu.Items.FirstOrDefault();
+ subMenu = menuItem?.Submenu;
+ }
+ if (menuItem == null)
+ {
+ menuItem = new NSMenuItem(menu.Text ?? "");
+ menuItem.Submenu = subMenu = new NSMenu(menu.Text ?? "");
+ }
+
foreach (var item in menu.Items)
{
- var subMenuItem = item.ToNSMenuItem();
+ var subMenuItem = item.ToNSMenuItem(menuItemCreator: menuItemCreator);
GetAccelerators(subMenuItem, item);
subMenu.AddItem(subMenuItem);
item.PropertyChanged += (sender, e) => (sender as MenuItem)?.UpdateNSMenuItem(subMenuItem, new string[] { e.PropertyName });
}
- nsMenu.AddItem(menuItem);
- menu.ToNSMenu(subMenu);
+ if (!nsMenu.Items.Contains(menuItem))
+ nsMenu.AddItem(menuItem);
+ menu.ToNSMenu(subMenu, menuItemCreator);
}
return nsMenu;
}
- public static NSMenuItem ToNSMenuItem(this MenuItem menuItem, int i = -1)
+ public static NSMenuItem ToNSMenuItem(this MenuItem menuItem, int i = -1, Func<MenuItem, NSMenuItem> menuItemCreator = null)
{
- var nsMenuItem = new NSMenuItem(menuItem.Text ?? "");
+ NSMenuItem nsMenuItem = null;
+ if (menuItemCreator == null)
+ nsMenuItem = new NSMenuItem(menuItem.Text ?? "");
+ else
+ nsMenuItem = menuItemCreator(menuItem);
if (i != -1)
nsMenuItem.Tag = i;
+
nsMenuItem.Enabled = menuItem.IsEnabled;
nsMenuItem.Activated += (sender, e) => ((IMenuItemController)menuItem).Activate();
if (!string.IsNullOrEmpty(menuItem.Icon))
return nsMenuItem;
}
+
+
public static void UpdateNSMenuItem(this MenuItem item, NSMenuItem menuItem, string[] properties)
{
foreach (var property in properties)
bool _isSuspended;
static int _storyboardMainMenuCount;
+ public Func<MenuItem, NSMenuItem> NativeMenuItemCreator { get; set; }
public abstract NSWindow MainWindow { get; }
protected override void Dispose(bool disposing)
Log.Warning("FormsApplicationDelegate", "Please provide a Main.storyboard to handle menus");
return;
}
-
+
ClearNSMenu(nsMenu);
- Element.GetMenu(_application).ToNSMenu(nsMenu);
+ SetupMainAppMenu(nsMenu);
+ }
+
+ protected virtual void SetupMainAppMenu(NSMenu nativeMenu)
+ {
+ var menu = Element.GetMenu(_application);
+ menu.ToNSMenu(nativeMenu, NativeMenuItemCreator);
}
static void ClearNSMenu(NSMenu menu)