# File: olcmenu.rb # Author: Craig Smith # # This source code copyright (C) 2009 Craig Smith # All rights reserved. # # Released under the terms of the GNU Public License # See COPYING file for additional information. # require 'utility/log' # Main menu interface object class OlcMenu logger "DEBUG" attr_accessor :title, :options, :state, :selected_opt, :editor, :default_array, :set_array, :default_hash, :calling, :init, :active_hash def initialize(title,calling,init) self.title = title self.calling = calling self.init = init self.options = [] self.state = nil self.selected_opt = nil self.editor = nil self.default_hash = {} self.active_hash = {} self.default_array = [] self.set_array = [] @menu_picks = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","R","S","T","U","V","W","X","Y","Z","Q"] end # Adds another hash item to the default hash # [+hash+] Hash to add def add_default_hash(hash) self.default_hash.merge!(hash) end # Adds a default item to default_array # [+item+] Item to add def add_default_item(item) self.default_array << item end # Numbered has arrays use both a default_hash and active_hash # to sink up the numbered selection it best to use the same method for keys # [+return+] Default and Active keys in the same array given def get_hash_keys keys = [] active_hash = {} if not active_hash keys = active_hash.keys keys.concat(default_hash.keys) keys.uniq! keys end # Sets the caller that initialized this menu def set_caller(parent,init) self.calling = parent self.init = init end # Resets the menus state and removes of menu items def reset self.options.clear self.default_hash.clear self.default_array.clear self.set_array.clear calling.send(init,"reset") if init and calling end # Finds the next unused menu_pick from menu_picks # [+return+] letter to use def get_next_pick @menu_picks.each do |p| found = false options.each do |opt| found = true if opt.pick=~/#{p}/i end return p if not found end end # Adds a standard menu option. uses :get_string # [+pick+] Item to pick, EG: A, B, etc. # [+name+] Items menu name EG: "Hair Color: " # [+target+] Object values to edit # [+obj+] Calling object # [+func+] Function that handles this option from calling object # [+return+] Undefined def add_std_option(pick, name, target, obj, func) opt = OlcMenuOption.new if pick opt.pick = pick else opt.pick = get_next_pick end opt.name = name opt.target = target opt.obj = obj opt.func = func opt.get_string = true self.options << opt end # Adds a editor menu option. uses :editor # [+pick+] Item to pick, EG: A, B, etc. # [+name+] Items menu name EG: "Hair Color: " # [+target+] Object values to edit # [+obj+] Calling object # [+func+] Function that handles this option from calling object # [+return+] Undefined def add_editor_option(pick, name, target, obj, func) opt = OlcMenuOption.new if pick opt.pick = pick else opt.pick = get_next_pick end opt.name = name opt.target = target opt.obj = obj opt.func = func opt.multi_line = true self.options << opt end # Makes a list of numbered options for array lists # [+arr+] Array to number # [+obj+] Calling object # [+func+] Function to handle call def add_numbered_option(arr,obj,func) opt = OlcMenuOption.new opt.target = arr opt.obj = obj opt.func = func opt.numbered_array = true self.options << opt end # Makes a list of numbered options for array lists of Oids that resolve object names # [+arr+] Array to number # [+obj+] Calling object # [+func+] Function to handle call def add_named_numbered_option(arr,obj,func) opt = OlcMenuOption.new opt.target = arr opt.obj = obj opt.func = func opt.named = true opt.numbered_array = true self.options << opt end # Very similar to add_numbered_option but uses two # builtin arrays and marks them. The OlcMenu object keeps # Track of both the standard array and what is set and passes # them at display time # [+obj+] Calling obj # [+func+] Function to handle call def add_toggled_numbered_options(obj,func) opt = OlcMenuOption.new opt.obj = obj opt.func = func opt.numbered_array = true opt.toggle = true self.options << opt end # Same as numbered_options but with default_hash key listings # [+hash+] Current hash of the object # [+obj+] Calling obj # [+func+] Function to handle call def add_hash_numbered_options(hash,obj,func) opt = OlcMenuOption.new opt.obj = obj opt.func = func hash = {} if not hash if hash.is_a? Hash opt.target = hash.dup self.active_hash = hash.dup opt.numbered_hash = true self.options << opt else log.error "OLC: add_hash_numbered_options: hash != Hash" end end # Adds a menu option that is typically text for an action or submenu # [+pick+] Item character to pick # [+name+] Name of option # [+obj+] Calling object # [+func+] Function that handles this option from calling object # [+target+] Optional target data to show # [+return+] Undefined def add_text_option(pick, name, obj, func, target=nil) opt = OlcMenuOption.new if pick opt.pick = pick else opt.pick = get_next_pick end opt.name = name opt.obj = obj opt.func = func opt.target = target self.options << opt end # Removes a menu option by name # [+name+] Name of option to remove def del_option_by_name(name) options.each do |opt| options.delete opt if opt.name == name end end # Updates target info. Call this after an update # [+pick+] Menu option pick # [+target+] New updated target info def update_target(pick, target) options.each do |opt| opt.target = target if opt.pick == pick end end # Print the menu def to_s msg = "-------------[ [color Green]#{title}[/color] ]------------\n" @options.each do |opt| if opt.numbered_array if opt.toggle msg << opt.to_s(default_array,set_array) else msg << opt.to_s end elsif opt.numbered_hash opt.target = get_hash_keys opt.active_hash = active_hash msg << opt.to_s end end @menu_picks.each do |p| options.each do |opt| msg << opt.to_s if opt.pick=~/#{p}/i end end msg << "Enter Choice> " msg end # Parses message from user to determine a match # [+m+] message # [+return+] Msg to print def parse(m) msg = "" case state when :get_string t=selected_opt.obj.send(selected_opt.func, m) if not t == nil update_target(selected_opt.pick, t) end self.state = nil self.selected_opt = nil return when :editor msg = editor.parse(m) if editor.done t=selected_opt.obj.send(selected_opt.func, editor.editstr) if t update_target(selected_opt.pick, t) end self.state = nil self.selected_opt = nil end return msg end options.each do |opt| if opt.is_match? m if opt.get_string msg = "#{opt.name}:" self.state = :get_string self.selected_opt = opt elsif opt.multi_line self.editor = OlcEditor.new(opt.target) self.state = :editor self.selected_opt = opt msg = editor.edit_display(opt.target) else opt.obj.send(opt.func, m) if opt.func end return msg end end msg end end