Last active
March 8, 2025 20:12
-
-
Save okay-type/43dafbd95bb5c3c92cefa4c8988091a1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# menuTitle: Sort Script Menu | |
import AppKit | |
from mojo.tools import CallbackWrapper | |
from mojo.subscriber import Subscriber, registerRoboFontSubscriber, registerSubscriberEvent, getRegisteredSubscriberEvents | |
class sort_script_menu(Subscriber): | |
debug = True | |
## https://stackoverflow.com/questions/7367438/sort-nsmenuitems-alphabetically-and-by-whether-they-have-submenus-or-not | |
def sortMenu(self, menu): | |
itemArray = menu.itemArray().copy() | |
# Create a descriptor that will sort files alphabetically | |
alphaDescriptor = AppKit.NSSortDescriptor.alloc().initWithKey_ascending_('title', True) | |
# itemArray = itemArray.sortedArrayUsingDescriptors_([alphaDescriptor]) | |
# Create a descriptor that will sort files alphabetically and based on existance of submenus | |
submenuDescriptor = AppKit.NSSortDescriptor.alloc().initWithKey_ascending_('hasSubmenu', False) | |
itemArray = itemArray.sortedArrayUsingDescriptors_([submenuDescriptor, alphaDescriptor]) | |
topItems = [] | |
middleItems = [] | |
bottomItems = [] | |
lastItems = [] | |
for item in itemArray: | |
title = item.title() | |
if title in ['Project', 'Project Scripts']: | |
topItems.append(item) | |
continue | |
elif title in ['Update Menu', 'Reveal Script folder']: | |
bottomItems.append(item) | |
continue | |
elif title in ['Mechanic', 'Mechanic 2']: | |
lastItems.append(item) | |
continue | |
else: | |
middleItems.append(item) | |
continue | |
# The following code fixes NSPopUpButton's confusion that occurs when | |
# we sort this list. NSPopUpButton listens to the NSMenu's add notifications | |
# and hides the first item. Sorting this blows it up. | |
# if item.isHidden(): | |
# item.setHidden_(False) | |
# While we're looping, if there's a submenu, go ahead and sort that, too. | |
# if item.hasSubmenu(): | |
# self.sortMenu(item.submenu()) | |
newItemArray = AppKit.NSMutableArray.alloc().init() | |
for item in topItems: | |
newItemArray.addObject_(item) | |
if len(topItems) > 0: | |
newItemArray.addObject_(AppKit.NSMenuItem.separatorItem()) | |
for item in middleItems: | |
newItemArray.addObject_(item) | |
if len(bottomItems) > 0: | |
newItemArray.addObject_(AppKit.NSMenuItem.separatorItem()) | |
for item in bottomItems: | |
newItemArray.addObject_(item) | |
if len(lastItems) > 0: | |
newItemArray.addObject_(AppKit.NSMenuItem.separatorItem()) | |
for item in lastItems: | |
newItemArray.addObject_(item) | |
sorted_menu = AppKit.NSArray.alloc().initWithArray_(newItemArray) | |
menu.setItemArray_(sorted_menu) | |
return | |
def sortExtensionsMenu(self): | |
# print('sort_script_menu sortExtensionsMenu') | |
menubar = AppKit.NSApp().mainMenu() | |
extensionsItem = menubar.itemWithTitle_('Extensions') | |
extensionsMenu = extensionsItem.submenu() | |
scriptsItem = menubar.itemWithTitle_('Scripts') | |
scriptsMenu = scriptsItem.submenu() | |
try: | |
self.sortMenu(extensionsMenu) | |
self.sortMenu(scriptsMenu) | |
except: | |
import traceback | |
print('Err') | |
print(traceback.format_exc()) | |
def roboFontDidFinishLaunching(self, info): | |
# print('sort_script_menu roboFontDidFinishLaunching') | |
self.sortExtensionsMenu() | |
def extensionDidRemoteInstall(self, info): | |
# print('sort_script_menu extensionDidRemoteInstall') | |
self.sortExtensionsMenu() | |
def extensionDidUninstall(self, info): | |
# print('sort_script_menu extensionDidUninstall') | |
self.sortExtensionsMenu() | |
def scriptsMenuChanged(self, info): | |
# print('sort_script_menu scriptsMenuChanged') | |
self.sortExtensionsMenu() | |
if 'com.ok.sort_script_menu.extensionInstalledEvent' not in getRegisteredSubscriberEvents().keys(): | |
registerSubscriberEvent( | |
subscriberEventName='com.ok.sort_script_menu.extensionInstalledEvent', | |
methodName='extensionDidRemoteInstall', | |
lowLevelEventNames=['com.robofontmechanic.extensionDidRemoteInstall'], | |
dispatcher='roboFont', | |
delay=1, | |
documentation='This is a custom subscriber method that looks for whether an extension installed on Mechanic.' | |
) | |
if 'com.ok.sort_script_menu.extensionUninstalledEvent' not in getRegisteredSubscriberEvents().keys(): | |
registerSubscriberEvent( | |
subscriberEventName='com.ok.sort_script_menu.extensionUninstalledEvent', | |
methodName='extensionDidUninstall', | |
lowLevelEventNames=['com.robofontmechanic.extensionDidUninstall'], | |
dispatcher='roboFont', | |
delay=1, | |
documentation='This is a custom subscriber method that looks for whether an extension uninstalled on Mechanic.' | |
) | |
if 'com.ok.sort_script_menu.scriptsMenuChangedEvent' not in getRegisteredSubscriberEvents().keys(): | |
registerSubscriberEvent( | |
subscriberEventName='com.ok.sort_script_menu.scriptsMenuChangedEvent', | |
methodName='scriptsMenuChanged', | |
lowLevelEventNames=['scriptsMenuChanged'], | |
dispatcher='roboFont', | |
delay=1, | |
documentation='This is a custom subscriber method for when Update Menu is clicked in the Scripts Menu.' | |
) | |
registerRoboFontSubscriber(sort_script_menu) |
Great, thanks. I hadn't update to the latest Mechanic. Reconfigured things to handle Mechanic and Mechanic 2. And to add them to the very bottom.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FYI: "Mechanic 2" is now "Mechanic" in the menu