public static void AddAppMenuItems(CommandManager manager, params object [] cmdIds) { //FIXME: we assume we get first pick of cmdIDs HIMenuItem mnu = HIToolbox.GetMenuItem((uint)CarbonCommandID.Hide); appMenu = mnu.MenuRef; var appMenuId = HIToolbox.GetMenuID(appMenu); for (int i = cmdIds.Length - 1; i >= 0; i--) { var cmdId = cmdIds[i]; if (cmdId == Command.Separator) { HIToolbox.InsertMenuSeparator(mnu.MenuRef, 0); continue; } Command cmd = manager.GetCommand(cmdId); if (cmd == null) { MonoDevelop.Core.LoggingService.LogError("Null command in Mac app menu for ID {0}", cmdId); continue; } uint macCmdId = GetNewMenuItemId(cmd); ushort pos = HIToolbox.InsertMenuItem(mnu.MenuRef, (cmd.Text ?? "").Replace("_", ""), 0, 0, macCmdId); SetMenuAccelerator(new HIMenuItem(mnu.MenuRef, pos), cmd.AccelKey); menuIdMap[cmdId] = appMenuId; } }
//updates commands and populates arrays and dynamic menus static CarbonEventHandlerStatus HandleMenuOpening(IntPtr callRef, IntPtr eventRef, IntPtr user_data) { DestroyOldMenuObjects(); menuOpenDepth++; try { IntPtr menuRef = Carbon.GetEventParameter(eventRef, CarbonEventParameterName.DirectObject, CarbonEventParameterType.MenuRef); //don't update dynamic menus recursively if (!mainMenus.Contains(menuRef) && menuRef != appMenu) { return(CarbonEventHandlerStatus.NotHandled); } // uint cmd = HIToolbox.GetMenuItemCommandID (new HIMenuItem (menuRef, 0)); CommandTargetRoute route = new CommandTargetRoute(); ushort count = HIToolbox.CountMenuItems(menuRef); for (ushort i = 1; i <= count; i++) { HIMenuItem mi = new HIMenuItem(menuRef, i); uint macCmdID = HIToolbox.GetMenuItemCommandID(mi); object cmdID; //link items if (macCmdID == linkCommandId) { if (IsGloballyDisabled) { HIToolbox.DisableMenuItem(mi); } else { HIToolbox.EnableMenuItem(mi); } continue; } //items that map to command objects if (!commands.TryGetValue(macCmdID, out cmdID) || cmdID == null) { continue; } CommandInfo cinfo = manager.GetCommandInfo(cmdID, route); menuIdMap[cmdID] = HIToolbox.GetMenuID(menuRef); UpdateMenuItem(menuRef, menuRef, ref i, ref count, macCmdID, cinfo); } } catch (Exception ex) { System.Console.WriteLine(ex); } return(CarbonEventHandlerStatus.NotHandled); }
static void UpdateAutoHide(HIMenuItem item) { IntPtr submenu; if (HIToolbox.GetMenuItemHierarchicalMenu(item.MenuRef, item.Index, out submenu) != CarbonMenuStatus.Ok) { return; } if (HasVisibleItems(submenu)) { HIToolbox.ChangeMenuItemAttributes(item, 0, MenuItemAttributes.Hidden); } else { HIToolbox.ChangeMenuItemAttributes(item, MenuItemAttributes.Hidden, 0); } }
static bool HasVisibleItems(IntPtr submenu) { var route = new CommandTargetRoute(); ushort count = HIToolbox.CountMenuItems(submenu); for (ushort i = 1; i <= count; i++) { HIMenuItem mi = new HIMenuItem(submenu, i); uint macCmdID = HIToolbox.GetMenuItemCommandID(mi); object cmdID; if (macCmdID == linkCommandId) { return(true); } if (!commands.TryGetValue(macCmdID, out cmdID) || cmdID == null) { continue; } CommandInfo cinfo = manager.GetCommandInfo(cmdID, route); if (cinfo.ArrayInfo != null) { foreach (CommandInfo ci in cinfo.ArrayInfo) { if (ci.Visible) { return(true); } } } else if (cinfo.Visible) { return(true); } } return(false); }
static void SetMenuAccelerator(HIMenuItem item, string accelKey) { MenuAccelModifier mod; ushort glyphCode, charCode, hardwareCode; if (GetAcceleratorKeys(accelKey, out glyphCode, out charCode, out hardwareCode, out mod)) { if (glyphCode != 0) { HIToolbox.SetMenuItemKeyGlyph(item.MenuRef, item.Index, (short)glyphCode); } else if (hardwareCode != 0) { HIToolbox.SetMenuItemCommandKey(item.MenuRef, item.Index, true, hardwareCode); } else { HIToolbox.SetMenuItemCommandKey(item.MenuRef, item.Index, false, charCode); } HIToolbox.SetMenuItemModifiers(item.MenuRef, item.Index, mod); } }
static void SetMenuItemAttributes(HIMenuItem item, CommandInfo ci, uint refcon) { MenuItemData data = new MenuItemData(); IntPtr text = IntPtr.Zero; try { if (ci.IsArraySeparator) { data.Attributes |= MenuItemAttributes.Separator; } else if (!ci.Visible) { data.Attributes |= MenuItemAttributes.Hidden; } else { data.Attributes &= ~MenuItemAttributes.Hidden; data.CFText = CoreFoundation.CreateString(GetCleanCommandText(ci)); //disable also when MD main window doesn't have toplevel focus, or commands will be //accessible when modal dialogs are active bool disabled = !ci.Enabled || IsGloballyDisabled; data.Enabled = !disabled; if (disabled) { data.Attributes |= MenuItemAttributes.Disabled; } ushort glyphCode, charCode, hardwareCode; MenuAccelModifier mod; if (GetAcceleratorKeys(ci.AccelKey, out glyphCode, out charCode, out hardwareCode, out mod)) { data.CommandKeyModifiers = mod; if (glyphCode != 0) { data.CommandKeyGlyph = glyphCode; data.Attributes ^= MenuItemAttributes.UseVirtualKey; } else if (hardwareCode != 0) { data.CommandVirtualKey = (char)hardwareCode; data.Attributes |= MenuItemAttributes.UseVirtualKey; } else { data.CommandKey = (char)charCode; data.Attributes ^= MenuItemAttributes.UseVirtualKey; } } //else{ //FIXME: remove existing commands if necessary data.Mark = ci.Checked ? ci.CheckedInconsistent ? '-' //FIXME: is this a good symbol for CheckedInconsistent? : (char)MenuGlyphs.Checkmark : '\0'; data.ReferenceConstant = refcon; } HIToolbox.SetMenuItemData(item.MenuRef, item.Index, false, ref data); } finally { if (text != IntPtr.Zero) { CoreFoundation.Release(text); } } }
static void AddMenuItems (HIMenuItem afterItem, IEnumerable<CommandEntry> entries) { IntPtr parentMenu = afterItem.MenuRef; var menuId = HIToolbox.GetMenuID (parentMenu); var index = afterItem.Index; foreach (CommandEntry entry in entries) { var ces = entry as CommandEntrySet; if (ces != null) { var macMenuCmdId = (ces.AutoHide) ? autohideSubmenuCommandId : submenuCommandId; IntPtr menuRef = HIToolbox.CreateMenu (idSeq++, GetName (ces), MenuAttributes.CondenseSeparators); mainMenus.Add (menuRef); AddMenuItems (new HIMenuItem (menuRef, 0), ces); index = HIToolbox.InsertMenuItem (parentMenu, GetName (ces), index, 0, macMenuCmdId); HIToolbox.CheckResult (HIToolbox.SetMenuItemHierarchicalMenu (parentMenu, index, menuRef)); continue; } if (entry.CommandId == Command.Separator) { index = HIToolbox.InsertMenuSeparator (parentMenu, index); continue; } if (entry is LinkCommandEntry) { var lce = (LinkCommandEntry)entry; index = HIToolbox.InsertMenuItem (parentMenu, (lce.Text ?? "").Replace ("_", ""), index, 0, linkCommandId); HIToolbox.SetMenuItemReferenceConstant (new HIMenuItem (parentMenu, index), (uint)linkCommands.Count); linkCommands.Add (lce.Url); continue; } Command cmd = manager.GetCommand (entry.CommandId); if (cmd == null) { MonoDevelop.Core.LoggingService.LogError ( "Mac main menu item '{0}' maps to null command", entry.CommandId); continue; } if (cmd is CustomCommand) { MonoDevelop.Core.LoggingService.LogWarning ( "Mac main menu does not support custom command widget for command '{0}'", entry.CommandId); continue; } menuIdMap[entry.CommandId] = menuId; var acmd = cmd as ActionCommand; if (acmd == null) { MonoDevelop.Core.LoggingService.LogWarning ( "Mac main menu does not support command type '{0}' for command '{1}'", cmd.GetType (), entry.CommandId); continue; } uint macCmdId = GetMacID (entry.CommandId); index = HIToolbox.InsertMenuItem (parentMenu, (cmd.Text ?? "").Replace ("_", ""), index, 0, macCmdId); } }
public static void SetMenuItemReferenceConstant (HIMenuItem item, uint value) { CheckResult (SetMenuItemRefCon (item.MenuRef, item.Index, value)); }
public static void ChangeMenuItemAttributes (HIMenuItem item, MenuItemAttributes toSet, MenuItemAttributes toClear) { CheckResult (ChangeMenuItemAttributes (item.MenuRef, item.Index, toSet, toClear)); }
static void SetMenuItemAttributes (HIMenuItem item, CommandInfo ci, uint refcon) { MenuItemData data = new MenuItemData (); IntPtr text = IntPtr.Zero; try { if (ci.IsArraySeparator) { data.Attributes |= MenuItemAttributes.Separator; } else if (!ci.Visible) { data.Attributes |= MenuItemAttributes.Hidden; } else { data.Attributes &= ~MenuItemAttributes.Hidden; data.CFText = CoreFoundation.CreateString (GetCleanCommandText (ci)); //disable also when MD main window doesn't have toplevel focus, or commands will be //accessible when modal dialogs are active bool disabled = !ci.Enabled || IsGloballyDisabled; data.Enabled = !disabled; if (disabled) data.Attributes |= MenuItemAttributes.Disabled; ushort glyphCode, charCode, hardwareCode; MenuAccelModifier mod; if (GetAcceleratorKeys (ci.AccelKey, out glyphCode, out charCode, out hardwareCode, out mod)) { data.CommandKeyModifiers = mod; if (glyphCode != 0) { data.CommandKeyGlyph = glyphCode; data.Attributes ^= MenuItemAttributes.UseVirtualKey; } else if (hardwareCode != 0) { data.CommandVirtualKey = (char)hardwareCode; data.Attributes |= MenuItemAttributes.UseVirtualKey; } else { data.CommandKey = (char)charCode; data.Attributes ^= MenuItemAttributes.UseVirtualKey; } } //else{ //FIXME: remove existing commands if necessary data.Mark = ci.Checked ? ci.CheckedInconsistent ? '-' //FIXME: is this a good symbol for CheckedInconsistent? : (char)MenuGlyphs.Checkmark : '\0'; data.ReferenceConstant = refcon; } HIToolbox.SetMenuItemData (item.MenuRef, item.Index, false, ref data); } finally { if (text != IntPtr.Zero) CoreFoundation.Release (text); } }
static void SetMenuAccelerator (HIMenuItem item, string accelKey) { MenuAccelModifier mod; ushort glyphCode, charCode, hardwareCode; if (GetAcceleratorKeys (accelKey, out glyphCode, out charCode, out hardwareCode, out mod)) { if (glyphCode != 0) HIToolbox.SetMenuItemKeyGlyph (item.MenuRef, item.Index, (short)glyphCode); else if (hardwareCode != 0) HIToolbox.SetMenuItemCommandKey (item.MenuRef, item.Index, true, hardwareCode); else HIToolbox.SetMenuItemCommandKey (item.MenuRef, item.Index, false, charCode); HIToolbox.SetMenuItemModifiers (item.MenuRef, item.Index, mod); } }
public static void SetAppMenuItems(CommandManager manager, CommandEntrySet entrySet) { HIMenuItem mnu = HIToolbox.GetMenuItem((uint)CarbonCommandID.Hide); bool firstTime = appMenu == IntPtr.Zero; appMenu = mnu.MenuRef; var existingitems = GetMenuCommandIDs(appMenu).ToList(); for (int i = existingitems.Count - 1; i >= 0; i--) { var item = new HIMenuItem(appMenu, (ushort)(i + 1)); //if first time, keep all the existing items except QuitAndCloseAllWindows if (firstTime && existingitems [i] != (uint)CarbonCommandID.QuitAndCloseAllWindows) { //mark them so we can recognise and keep them in future //HIToolbox.SetMenuItemReferenceConstant (item, uint.MaxValue); continue; } // if it's not the first time, keep the original items we marked if (!firstTime && HIToolbox.GetMenuItemReferenceConstant(item) == UInt32.MaxValue) { continue; } //remove everything else HIToolbox.DeleteMenuItem(item); existingitems.RemoveAt(i); } // Iterate backwards over the entries. For each one, try to find a matching built-in item. If successful, // get all the items from that point to the last item that was not yet inserted, and insert them // at that point. var entries = entrySet.ToList(); int uninsertedCount = entries.Count; for (int i = entries.Count - 1; i >= 0; i--) { var entry = entries [i]; if (entry.CommandId == null || entry.CommandId == Command.Separator) { continue; } var id = GetMacID(entry.CommandId); //find an existing item int match = existingitems.IndexOf(id); if (match >= 0) { //if there are uninserted items *after* this one, insert them at this point if ((uninsertedCount - i) > 0) { var items = entries.Skip(i + 1).Take(uninsertedCount - i - 2); var insertionPoint = new HIMenuItem(appMenu, (ushort)(match + 1)); AddMenuItems(insertionPoint, items); } uninsertedCount = i; } } // Finally, insert any remaining items at the beginning/top of the menu. if (uninsertedCount > 0) { AddMenuItems(new HIMenuItem(appMenu, 0), entries.Take(uninsertedCount)); } }
static void AddMenuItems(HIMenuItem afterItem, IEnumerable <CommandEntry> entries) { IntPtr parentMenu = afterItem.MenuRef; var menuId = HIToolbox.GetMenuID(parentMenu); var index = afterItem.Index; foreach (CommandEntry entry in entries) { var ces = entry as CommandEntrySet; if (ces != null) { var macMenuCmdId = (ces.AutoHide) ? autohideSubmenuCommandId : submenuCommandId; IntPtr menuRef = HIToolbox.CreateMenu(idSeq++, GetName(ces), MenuAttributes.CondenseSeparators); mainMenus.Add(menuRef); AddMenuItems(new HIMenuItem(menuRef, 0), ces); index = HIToolbox.InsertMenuItem(parentMenu, GetName(ces), index, 0, macMenuCmdId); HIToolbox.CheckResult(HIToolbox.SetMenuItemHierarchicalMenu(parentMenu, index, menuRef)); continue; } if (entry.CommandId == Command.Separator) { index = HIToolbox.InsertMenuSeparator(parentMenu, index); continue; } if (entry is LinkCommandEntry) { var lce = (LinkCommandEntry)entry; index = HIToolbox.InsertMenuItem(parentMenu, (lce.Text ?? "").Replace("_", ""), index, 0, linkCommandId); HIToolbox.SetMenuItemReferenceConstant(new HIMenuItem(parentMenu, index), (uint)linkCommands.Count); linkCommands.Add(lce.Url); continue; } Command cmd = manager.GetCommand(entry.CommandId); if (cmd == null) { MonoDevelop.Core.LoggingService.LogError( "Mac main menu item '{0}' maps to null command", entry.CommandId); continue; } if (cmd is CustomCommand) { MonoDevelop.Core.LoggingService.LogWarning( "Mac main menu does not support custom command widget for command '{0}'", entry.CommandId); continue; } menuIdMap[entry.CommandId] = menuId; var acmd = cmd as ActionCommand; if (acmd == null) { MonoDevelop.Core.LoggingService.LogWarning( "Mac main menu does not support command type '{0}' for command '{1}'", cmd.GetType(), entry.CommandId); continue; } uint macCmdId = GetMacID(entry.CommandId); index = HIToolbox.InsertMenuItem(parentMenu, (cmd.Text ?? "").Replace("_", ""), index, 0, macCmdId); } }
public static void DeleteMenuItem (HIMenuItem item) { DeleteMenuItem (item.MenuRef, item.Index); }
public static void SetAppMenuItems (CommandManager manager, CommandEntrySet entrySet) { HIMenuItem mnu = HIToolbox.GetMenuItem ((uint)CarbonCommandID.Hide); bool firstTime = appMenu == IntPtr.Zero; appMenu = mnu.MenuRef; var existingitems = GetMenuCommandIDs (appMenu).ToList (); for (int i = existingitems.Count - 1; i >= 0; i--) { var item = new HIMenuItem (appMenu, (ushort)(i + 1)); //if first time, keep all the existing items except QuitAndCloseAllWindows if (firstTime && existingitems [i] != (uint)CarbonCommandID.QuitAndCloseAllWindows) { //mark them so we can recognise and keep them in future //HIToolbox.SetMenuItemReferenceConstant (item, uint.MaxValue); continue; } // if it's not the first time, keep the original items we marked if (!firstTime && HIToolbox.GetMenuItemReferenceConstant (item) == UInt32.MaxValue) { continue; } //remove everything else HIToolbox.DeleteMenuItem (item); existingitems.RemoveAt (i); } // Iterate backwards over the entries. For each one, try to find a matching built-in item. If successful, // get all the items from that point to the last item that was not yet inserted, and insert them // at that point. var entries = entrySet.ToList (); int uninsertedCount = entries.Count; for (int i = entries.Count - 1; i >= 0; i--) { var entry = entries [i]; if (entry.CommandId == null || entry.CommandId == Command.Separator) continue; var id = GetMacID (entry.CommandId); //find an existing item int match = existingitems.IndexOf (id); if (match >= 0) { //if there are uninserted items *after* this one, insert them at this point if ((uninsertedCount - i) > 0) { var items = entries.Skip (i + 1).Take (uninsertedCount - i - 2); var insertionPoint = new HIMenuItem (appMenu, (ushort)(match + 1)); AddMenuItems (insertionPoint, items); } uninsertedCount = i; } } // Finally, insert any remaining items at the beginning/top of the menu. if (uninsertedCount > 0) { AddMenuItems (new HIMenuItem (appMenu, 0), entries.Take (uninsertedCount)); } }
public static void DisableMenuItem (HIMenuItem item) { CheckResult (DisableMenuItem (item.MenuRef, item.Index)); }
//updates commands and populates arrays and dynamic menus //NOTE: when Help menu is opened, Mac OS calls this for ALL menus because the Help menu can search menu items static CarbonEventHandlerStatus HandleMenuOpening (IntPtr callRef, IntPtr eventRef, IntPtr user_data) { DestroyOldMenuObjects (); menuOpenDepth++; try { IntPtr menuRef = Carbon.GetEventParameter (eventRef, CarbonEventParameterName.DirectObject, CarbonEventParameterType.MenuRef); //don't update dynamic menus recursively if (!mainMenus.Contains (menuRef) && menuRef != appMenu) return CarbonEventHandlerStatus.NotHandled; // uint cmd = HIToolbox.GetMenuItemCommandID (new HIMenuItem (menuRef, 0)); CommandTargetRoute route = new CommandTargetRoute (); ushort count = HIToolbox.CountMenuItems (menuRef); for (ushort i = 1; i <= count; i++) { HIMenuItem mi = new HIMenuItem (menuRef, i); uint macCmdID = HIToolbox.GetMenuItemCommandID (mi); object cmdID; //link items if (macCmdID == linkCommandId) { if (IsGloballyDisabled) HIToolbox.DisableMenuItem (mi); else HIToolbox.EnableMenuItem (mi); continue; } if (macCmdID == submenuCommandId) continue; if (macCmdID == autohideSubmenuCommandId) { UpdateAutoHide (new HIMenuItem (menuRef, i)); continue; } //items that map to command objects if (!commands.TryGetValue (macCmdID, out cmdID) || cmdID == null) continue; CommandInfo cinfo = manager.GetCommandInfo (cmdID, route); menuIdMap[cmdID] = HIToolbox.GetMenuID (menuRef); UpdateMenuItem (menuRef, menuRef, ref i, ref count, macCmdID, cinfo); } } catch (Exception ex) { System.Console.WriteLine (ex); } return CarbonEventHandlerStatus.NotHandled; }
public static uint GetMenuItemCommandID (HIMenuItem item) { uint id; CheckResult (GetMenuItemCommandID (item.MenuRef, item.Index, out id)); return id; }
static void UpdateAutoHide (HIMenuItem item) { IntPtr submenu; if (HIToolbox.GetMenuItemHierarchicalMenu (item.MenuRef, item.Index, out submenu) != CarbonMenuStatus.Ok) return; if (HasVisibleItems (submenu)) { HIToolbox.ChangeMenuItemAttributes (item, 0, MenuItemAttributes.Hidden); } else { HIToolbox.ChangeMenuItemAttributes (item, MenuItemAttributes.Hidden, 0); } }
public static uint GetMenuItemReferenceConstant (HIMenuItem item) { uint val; CheckResult (GetMenuItemRefCon (item.MenuRef, item.Index, out val)); return val; }
static bool HasVisibleItems (IntPtr submenu) { var route = new CommandTargetRoute (); ushort count = HIToolbox.CountMenuItems (submenu); for (ushort i = 1; i <= count; i++) { HIMenuItem mi = new HIMenuItem (submenu, i); uint macCmdID = HIToolbox.GetMenuItemCommandID (mi); object cmdID; if (macCmdID == linkCommandId) return true; if (!commands.TryGetValue (macCmdID, out cmdID) || cmdID == null) continue; CommandInfo cinfo = manager.GetCommandInfo (cmdID, route); if (cinfo.ArrayInfo != null) { foreach (CommandInfo ci in cinfo.ArrayInfo) if (ci.Visible) return true; } else if (cinfo.Visible) { return true; } } return false; }