lib/everyday-menu/menu.rb
module EverydayMenu
class Menu
include MyAccessors
def self.def_accessors
my_attr_writer :label
my_attr_accessor_bool :servicesMenu, :windowsMenu, :helpMenu, :mainMenu
my_attr_reader_bool :statusMenu
my_attr_reader :statusItemTitle, :statusItemIcon, :statusItemViewClass, :statusItemLength, :statusItem
attr_reader :menu, :builder
end
def_accessors
def self.create(label, title, options = {}, &block)
new(label, &block).tap { |menu| setup_obj(menu, label, title, options) }
end
def initialize(label, &block)
@label = label
@builder = block
@menu = NSMenu.alloc.init
@menu.delegate = self
@menuItems = MenuItemList.new(@menu)
@mainMenu = false
@statusMenu = false
@servicesMenu = false
@windowsMenu = false
@helpMenu = false
@statusItemTitle = nil
@statusItemIcon = nil
@statusItemViewClass = nil
@statusItemLength = nil
end
def menuNeedsUpdate(menu)
flags = (NSEvent.modifierFlags & NSDeviceIndependentModifierFlagsMask)
shouldHideSecretMenu = !(flags == NSAlternateKeyMask)
@menuItems.each { |menuItem|
menuItem.item.setHidden(shouldHideSecretMenu) if menuItem.opt?
}
end
def menuItemFromMenu!
@mainMenuItem ||= MenuItem.create(self[:label], self[:title], submenu: self)
self
end
alias :menu_item_for_menu! :menuItemFromMenu!
def menuItem
@mainMenuItem.item
end
alias :menu_item :menuItem
def subscribe(label, command_id = nil, &block)
self.items[label].subscribe(command_id, &block)
end
def <<(item)
@menuItems << item
end
def containedObject
@menu
end
def runOnBuild
@@buildBlocks ||= {}
@@buildBlocks.each { |block| block[1].call(self) if self.is(block[0]) }
@menuItems.each { |item| item.runOnBuild }
end
def self.registerBuildBlock(field, &block)
@@buildBlocks ||= {}
@@buildBlocks[field] = block
end
def self.def_build_blocks
registerBuildBlock(:services_menu) { |menu| NSApp.servicesMenu = menu.menu }
registerBuildBlock(:windows_menu) { |menu| NSApp.windowsMenu = menu.menu }
registerBuildBlock(:help_menu) { |menu| NSApp.helpMenu = menu.menu }
registerBuildBlock(:status_menu) { |menu| menu.createStatusItem! }
end
def_build_blocks
def label
@label ||= nil
end
def setStatusItemTitle(title)
@mainMenu = false unless title.nil?
@statusItemTitle = title
@statusMenu = true unless title.nil?
end
def setStatusItemIcon(icon)
@mainMenu = false unless icon.nil?
@statusItemIcon = icon
@statusMenu = true unless icon.nil?
end
def setStatusItemViewClass(viewClass)
@mainMenu = false unless viewClass.nil?
@statusItemViewClass = viewClass
@statusMenu = true unless viewClass.nil?
end
def setStatusItemLength(length)
@mainMenu = false unless length.nil?
@statusItemLength = length
@statusMenu = true unless length.nil?
end
def createStatusItem!
statusBar = NSStatusBar.systemStatusBar
@statusItem = statusBar.statusItemWithLength(@statusItemLength || NSSquareStatusItemLength)
@statusItem.highlightMode = true
@statusItem.menu = self.menu
unless @statusItemViewClass.nil?
statusItemView = @statusItemViewClass.viewWithStatusItem(@statusItem)
@statusItem.menu.delegate = @statusItemView
@statusItem.view = statusItemView
end
@statusItem.title = @statusItemTitle
@statusItem.image = @statusItemIcon
@statusItem
end
def items
@menuItems
end
def selectItem(label)
item = self.items[label]
item.execute
end
def self.def_aliases
alias :statusItemTitle= :setStatusItemTitle
alias :status_item_title= :setStatusItemTitle
alias :statusItemIcon= :setStatusItemIcon
alias :status_item_icon= :setStatusItemIcon
alias :statusItemViewClass= :setStatusItemViewClass
alias :status_item_view_class= :setStatusItemViewClass
end
def_aliases
end
class MenuItemList
def initialize(menu)
@menuItems = {}
@menu = menu
end
def <<(item)
previousItemTag = @menuItems.keys.last || 0
item[:tag] = previousItemTag + 1
@menuItems[item[:tag]] = item
@menu.addItem item.menuItem
end
def [](labelOrTag)
(labelOrTag.is_a? Fixnum) ? @menuItems[labelOrTag] : @menuItems.values.find { |item| item.label == labelOrTag }
end
def selectItem(label)
item = self[label]
item.execute
end
alias :select_item :selectItem
def selectItemByMember(member)
item = @menuItems.values.find do |i|
i[:represented_object] == member
end
item.execute
end
alias :select_item_by_member :selectItemByMember
def each(&block)
@menuItems.values.each(&block)
end
end
end