<commit_before>//
//  MenuItemsAssistant.swift
//  BurntCocoaUI
//
//  Created by <NAME> on 14/05/2015.
//  Copyright (c) 2015 <NAME>. All rights reserved.
//

import Cocoa


public struct MenuItemCustomization<T: UIChoiceRepresentative> {
	/**
		Customize the title dynamically, called for each menu item representative.
	*/
	public var title: ((menuItemRepresentative: T) -> String)?
	/**
		Customize the action & target dynamically, called for each menu item representative.
	*/
	public var actionAndTarget: ((menuItemRepresentative: T) -> (action: Selector, target: AnyObject?))?
	/**
		Customize the represented object, called for each menu item representative.
	*/
	public var representedObject: ((menuItemRepresentative: T) -> AnyObject?)?
	/**
		Customize the integer tag, called for each menu item representative.
	*/
	public var tag: ((menuItemRepresentative: T) -> Int?)?
	/**
		Customize the state (NSOnState / NSOffState / NSMixedState), called for each menu item representative.
	*/
	public var state: ((menuItemRepresentative: T) -> Int)?
	/**
		Customize whether the menu item is enabled, called for each menu item representative.
	*/
	public var enabled: ((menuItemRepresentative: T) -> Bool)?
	/**
	Customize the submenu, called for each menu item representative.
	*/
	public var additionalSetUp: ((menuItemRepresentative: T, menuItem: NSMenuItem) -> ())?
}


public class MenuItemsAssistantCache<T: UIChoiceRepresentative> {
	typealias ItemUniqueIdentifier = T.UniqueIdentifier
	
	/// Menu items are cached so they are not thrown away and recreated every time.
	var uniqueIdentifierToMenuItems = [ItemUniqueIdentifier: NSMenuItem]()
}


/**
MenuItemsAssistant
*/
public class MenuItemsAssistant<T: UIChoiceRepresentative> {
	public typealias Item = T
	public typealias ItemUniqueIdentifier = Item.UniqueIdentifier
	
	/**
		Pass your implementation of UIChoiceRepresentative. Use nil for separator menu items.
	*/
	public var menuItemRepresentatives: [Item?]!
	
	/**
		Customize the menu item’s title, action, etc with this.
	*/
	public var customization = MenuItemCustomization<Item>()
	
	/**
	Creates menu items based on the array of `menuItemRepresentatives`
	
	- parameter cache: Pass this multiple times to createItems() to reuse menu items.
	*/
	public func createItems(cache cache: MenuItemsAssistantCache<Item>?) -> [NSMenuItem] {
		if menuItemRepresentatives == nil {
			fatalError("Must set .menuItemRepresentatives before calling createItems()")
		}
		
		var previousCachedIdentifiers = Set<ItemUniqueIdentifier>()
		if let cache = cache {
			previousCachedIdentifiers.unionInPlace(cache.uniqueIdentifierToMenuItems.keys)
		}
		
		let customization = self.customization
		
		let items = menuItemRepresentatives.map { menuItemRepresentative -> NSMenuItem in
			if let menuItemRepresentative = menuItemRepresentative {
				let title: String = customization.title?(menuItemRepresentative: menuItemRepresentative) ?? menuItemRepresentative.title
				let representedObject: AnyObject? = customization.representedObject?(menuItemRepresentative: menuItemRepresentative)
				let tag: Int = customization.tag?(menuItemRepresentative: menuItemRepresentative) ?? 0
				let state: Int = customization.state?(menuItemRepresentative: menuItemRepresentative) ?? NSOffState
				let enabled: Bool = customization.enabled?(menuItemRepresentative: menuItemRepresentative) ?? true
				let (action, target) = customization.actionAndTarget?(menuItemRepresentative: menuItemRepresentative) ?? (nil, nil)
				
				let uniqueIdentifier = menuItemRepresentative.uniqueIdentifier
				previousCachedIdentifiers.remove(uniqueIdentifier)
				
				let item: NSMenuItem
				if let cachedItem = cache?.uniqueIdentifierToMenuItems[uniqueIdentifier] {
					item = cachedItem
				}
				else {
					item = NSMenuItem()
					cache?.uniqueIdentifierToMenuItems[uniqueIdentifier] = item
				}
				
				item.title = title
				item.representedObject = representedObject
				item.action = action
				item.target = target
				item.tag = tag
				item.state = state
				item.enabled = enabled<commit_msg>Add ability to customize images of menu items<commit_after>//
//  MenuItemsAssistant.swift
//  BurntCocoaUI
//
//  Created by <NAME> on 14/05/2015.
//  Copyright (c) 2015 <NAME>. All rights reserved.
//

import Cocoa


public struct MenuItemCustomization<T: UIChoiceRepresentative> {
	/**
		Customize the title dynamically, called for each menu item representative.
	*/
	public var title: ((menuItemRepresentative: T) -> String)?
	/**
		Customize the action & target dynamically, called for each menu item representative.
	*/
	public var actionAndTarget: ((menuItemRepresentative: T) -> (action: Selector, target: AnyObject?))?
	/**
		Customize the represented object, called for each menu item representative.
	*/
	public var representedObject: ((menuItemRepresentative: T) -> AnyObject?)?
	/**
		Customize the integer tag, called for each menu item representative.
	*/
	public var tag: ((menuItemRepresentative: T) -> Int?)?
	/**
		Customize the state (NSOnState / NSOffState / NSMixedState), called for each menu item representative.
	*/
	public var state: ((menuItemRepresentative: T) -> Int)?
	/**
		Customize whether the menu item is enabled, called for each menu item representative.
	*/
	public var enabled: ((menuItemRepresentative: T) -> Bool)?
	/**
	Customize the image, called for each menu item representative.
	*/
	public var image: ((menuItemRepresentative: T) -> NSImage?)?
	/**
	Customize the submenu, called for each menu item representative.
	*/
	public var additionalSetUp: ((menuItemRepresentative: T, menuItem: NSMenuItem) -> ())?
}


public class MenuItemsAssistantCache<T: UIChoiceRepresentative> {
	typealias ItemUniqueIdentifier = T.UniqueIdentifier
	
	/// Menu items are cached so they are not thrown away and recreated every time.
	var uniqueIdentifierToMenuItems = [ItemUniqueIdentifier: NSMenuItem]()
}


/**
MenuItemsAssistant
*/
public class MenuItemsAssistant<T: UIChoiceRepresentative> {
	public typealias Item = T
	public typealias ItemUniqueIdentifier = Item.UniqueIdentifier
	
	/**
		Pass your implementation of UIChoiceRepresentative. Use nil for separator menu items.
	*/
	public var menuItemRepresentatives: [Item?]!
	
	/**
		Customize the menu item’s title, action, etc with this.
	*/
	public var customization = MenuItemCustomization<Item>()
	
	/**
	Creates menu items based on the array of `menuItemRepresentatives`
	
	- parameter cache: Pass this multiple times to createItems() to reuse menu items.
	*/
	public func createItems(cache cache: MenuItemsAssistantCache<Item>?) -> [NSMenuItem] {
		if menuItemRepresentatives == nil {
			fatalError("Must set .menuItemRepresentatives before calling createItems()")
		}
		
		var previousCachedIdentifiers = Set<ItemUniqueIdentifier>()
		if let cache = cache {
			previousCachedIdentifiers.unionInPlace(cache.uniqueIdentifierToMenuItems.keys)
		}
		
		let customization = self.customization
		
		let items = menuItemRepresentatives.map { menuItemRepresentative -> NSMenuItem in
			if let menuItemRepresentative = menuItemRepresentative {
				let title = customization.title?(menuItemRepresentative: menuItemRepresentative) ?? menuItemRepresentative.title
				let representedObject = customization.representedObject?(menuItemRepresentative: menuItemRepresentative)
				let tag = customization.tag?(menuItemRepresentative: menuItemRepresentative) ?? 0
				let state = customization.state?(menuItemRepresentative: menuItemRepresentative) ?? NSOffState
				let enabled = customization.enabled?(menuItemRepresentative: menuItemRepresentative) ?? true
				let image = customization.image?(menuItemRepresentative: menuItemRepresentative)
				let (action, target) = customization.actionAndTarget?(menuItemRepresentative: menuItemRepresentative) ?? (nil, nil)
				
				let uniqueIdentifier = menuItemRepresentative.uniqueIdentifier
				previousCachedIdentifiers.remove(uniqueIdentifier)
				
				let item: NSMenuItem
				if let cachedItem = cache?.uniqueIdentifierToMenuItems[uniqueIdentifier] {
					item = cachedItem
				}
				else {
					item = NSMenuItem()
					cache?.uniqueIdentifierToMenuItems[uniqueIdentifier] = item
				}
				
				item.title = title
				item.representedObject = representedObject
				item.action = action
				item.target = target
				item.tag = tag
				item.state = state
				item.enabled = enabled
				item.image = image
{'fraction_non_alphanumeric': 0.09045524783073815, 'fraction_numerical': 0.0030904552478307383, 'mean_word_length': 4.531886916502301, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5920417', 'n_tokens_mistral': 2599, 'n_tokens_neox': 2246, 'n_words': 688}