# 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