class Canis::Menu
class Menu. Contains menuitems, and can be a menuitem itself.
Opens out another list of menuitems.
Attributes
Public Class Methods
Canis::MenuItem::new
# File lib/canis/core/widgets/rmenu.rb, line 202 def initialize text, &block @text = text @items = [] @enabled = true @current_menu = [] super text, nil, &block @row ||=10 @col ||=10 @coffset = 0 @@menus ||= [] @active_index = nil # 2011-09-25 V1.3.1 otherwise crashing in select_right end
Public Instance Methods
item could be menuitem or another menu (precreated)
# File lib/canis/core/widgets/rmenu.rb, line 222 def add menuitem #$log.debug " YYYY inside add menuitem #{menuitem.text} " @items << menuitem return self end
# File lib/canis/core/widgets/rmenu.rb, line 249 def add_separator @items << MenuSeparator.new end
private returns length of longest item in array
# File lib/canis/core/widgets/rmenu.rb, line 542 def array_width a longest = a.max {|a,b| a.to_s.length <=> b.to_s.length } #$log.debug "array width #{longest}" longest.to_s.length end
checks given key against current menu's items and fires key if added on 2008-11-27 12:07
# File lib/canis/core/widgets/rmenu.rb, line 642 def check_mnemonics cmenu, ch # $log.debug "inside check_mnemonics #{ch}" key = ch.chr.downcase rescue "" cmenu.items.each do |item| next if !item.respond_to? :mnemonic or item.mnemonic.nil? # $log.debug "inside check_mnemonics #{item.mnemonic}" if key == item.mnemonic.downcase && item.enabled # 2010-09-11 00:03 enabled ret = item.fire return ret #0 2009-01-23 00:45 end end return :UNHANDLED end
# File lib/canis/core/widgets/rmenu.rb, line 471 def create_window # menu margin = 2 # flush against parent @width = array_width(@items) + 1 # adding 1 since menus append a ">" 2011-09-24 $log.debug "create window menu #{@text}: r #{@row} ,col #{@col}, wd #{@width} " t = @row+1 h = @items.length+3 ww = @width+margin ww1 = @width max = Ncurses.LINES-1 if t + h > max t = 2 # one below menubar, not touching if h > max i = ((h*1.0)/max).ceil h = max - 1 ww = ww * i # FIXME we need to calculate end end # t + 1 $log.debug "create window menu #{@text}: t #{t} ,h #{h}, w: #{ww} , col #{@col} max #{max} " #@layout = { :height => @items.length+3, :width => ww, :top => @row+1, :left => @col } # earlier col had the offset to start the next level, I was not using it to print # but with mulitple cols i am using it. So, this col will overwrite existing menu. @layout = { :height => h-1, :width => ww, :top => t, :left => @coffset } @win = Canis::Window.new(@layout) @window = @win @window.name = "WINDOW:menu" @color_pair ||= get_color($datacolor, @color, @bgcolor) @rev_color_pair ||= get_color($reversecolor, @color, @bgcolor) @win.bkgd(Ncurses.COLOR_PAIR(@color_pair)); @panel = @win.panel #@window.printstring( 0, 0, "+%s+" % ("-"*@width), $reversecolor) @window.printstring( 0, 0, "+%s+" % ("-"*(ww1)), @rev_color_pair) saved_r = 1 r = 1 #saved_c = @col+@width+margin # margins??? saved_c = 0 ; # actual program uses 0 in repain for col c = saved_c $log.debug "create window menu #{@text}: first col r #{r} ,c #{c}" @items.each do |item| #break if r > h # added 2011-09-24 for large number of items - causes error if r >= h-2 @window.printstring( h-2, c, "+%s+" % ("-"*(ww1)), @rev_color_pair) r = saved_r c += (@width + 2) @window.printstring( 0, c, "+%s+" % ("-"*(ww1)), @rev_color_pair) $log.debug "create window menu #{@text}: new col r #{r} ,c #{c}, #{item.text} " end item.row = r item.col = c item.coffset = @coffset+@width+margin # margins??? item.width = @width #item.window = @window item.parent = self item.color = @color; item.bgcolor = @bgcolor item.repaint r+=1 end # @window.printstring( r, 0, "+%s+" % ("-"*@width), $reversecolor) # changed 2011 2011-09-24 @window.printstring( h-2, 0, "+%s+" % ("-"*(ww1)), @rev_color_pair) # in case of multiple rows @window.printstring( r, c, "+%s+" % ("-"*(ww1)), @rev_color_pair) # added box with proper ncurses extended char set 2014-08-27 - 14:30 @window.print_border_only 0,0,h-2, ww, @rev_color_pair select_item 0 @window.refresh return @window end
destroys windows and each item within (submenus)
# File lib/canis/core/widgets/rmenu.rb, line 548 def destroy $log.debug "DESTROY menu #{@text}" return if @window.nil? @visible = false #2014-05-12 - 20:53 next 3 replaced with destroy since destroy refreshes root window. #panel = @window.panel #Ncurses::Panel.del_panel(panel.pointer) if !panel.nil? #@window.delwin if !@window.nil? @window.destroy @items.each do |item| item.destroy end @window = nil end
menu -
# File lib/canis/core/widgets/rmenu.rb, line 273 def fire $log.debug "menu fire called: #{text} " if @window.nil? #repaint # added 2011-09-24 adding ability to generate list of items if @item_list # generate a list, but we need to know what to do with that list. @items = [] l = @item_list.call self, *@item_list_args if !@item_list.nil? if l.nil? || l.size == 0 item(:NO_MENUITEMS) else # for each element returned create a menuitem, and attach the command to it. l.each { |e| it = item(e); if @command # there should be a command otherwise what's the point it.command(@args) do @command.call(it, it.text) end; else it.command(@args) do alert("No command attached to #{it.text} ") end; $log.warn "No command attached to item_list " end } end $log.debug "menu got items #{@items.count} " end if @items.empty? # user did not specify any items item(:NO_MENUITEMS) end create_window if !@parent.is_a? Canis::MenuBar @parent.current_menu << self @@menus << self # NEW end else ### shouod this not just show ? $log.debug "menu fire called: #{text} ELSE XXX WHEN IS THIS CALLED ? 658 #{@items[@active_index].text} " if @active_index # sometimes no menu item specified 2011-09-24 NEWMENU return @items[@active_index].fire # this should happen if selected. else selected() end end #@action.call if !@action.nil? end
added 2009-01-21 12:09 NEW
# File lib/canis/core/widgets/rmenu.rb, line 255 def get_item i @items[i] end
menu LEFT, RIGHT, DOWN, UP, ENTER item could be menuitem or another menu
# File lib/canis/core/widgets/rmenu.rb, line 565 def handle_key ch if !@current_menu.empty? cmenu = @current_menu.last else cmenu = self end if !@@menus.empty? cmenu = @@menus.last else cmenu = self end case ch when KEY_DOWN cmenu.select_next_item #return cmenu.fire # XXX 2010-10-16 21:39 trying out if cmenu.is_a? Canis::Menu #alert "is a menu" # this gets triggered even when we are on items end when KEY_UP cmenu.select_prev_item when KEY_ENTER, 10, 13, 32 # added 32 2008-11-27 23:50 return cmenu.fire when KEY_LEFT if cmenu.parent.is_a? Canis::Menu #$log.debug "LEFT IN MENU : #{cmenu.parent.class} len: #{cmenu.parent.current_menu.length}" #$log.debug "left IN MENU : #{cmenu.parent.class} len: #{cmenu.current_menu.length}" end ret = cmenu.select_left_item # 2011-09-24 V1.3.1 attempt to goto left item if columns if ret == :UNHANDLED if cmenu.parent.is_a? Canis::MenuBar #and !cmenu.parent.current_menu.empty? #$log.debug " ABOU TO DESTROY DUE TO LEFT" cmenu.current_menu.pop @@menus.pop ## NEW cmenu.destroy return :UNHANDLED end # LEFT on a menu list allows me to close and return to higher level if cmenu.parent.is_a? Canis::Menu #and !cmenu.parent.current_menu.empty? #$log.debug " ABOU TO DESTROY DUE TO LEFT" cmenu.current_menu.pop @@menus.pop ## NEW cmenu.destroy #return :UNHANDLED end end when KEY_RIGHT $log.debug "RIGHTIN MENU : #{text} " if cmenu.active_index if cmenu.items[cmenu.active_index].is_a? Canis::Menu #alert "could fire here cmenu: #{cmenu.text}, par: #{cmenu.parent.text} " cmenu.fire return #$log.debug "right IN MENU : #{cmenu.parent.class} len: #{cmenu.parent.current_menu.length}" #$log.debug "right IN MENU : #{cmenu.parent.class} len: #{cmenu.current_menu.length}" end end # This introduces a bug if no open items ret = cmenu.select_right_item # 2011-09-24 V1.3.1 attempt to goto right item if columns #alert "attempting to select right #{ret} " if ret == :UNHANDLED #if cmenu.parent.is_a? Canis::Menu and !cmenu.parent.current_menu.empty? if cmenu.parent.is_a? Canis::MenuBar #and !cmenu.current_menu.empty? $log.debug " ABOU TO DESTROY DUE TO RIGHT" cmenu.current_menu.pop @@menus.pop cmenu.destroy return :UNHANDLED end end else ret = check_mnemonics cmenu, ch return ret end end
# File lib/canis/core/widgets/rmenu.rb, line 452 def highlight tf=true # menu if @parent.is_a? Canis::MenuBar # top level menu #acolor = get_color($datacolor, @bgcolor, @color) #@parent.window.printstring( @row, @col, " %s " % text, acolor) @color_pair ||= get_color($reversecolor, @color, @bgcolor) att = Ncurses::A_REVERSE @parent.window.mvchgat(y=@row, x=@col+1, text.length+1, att, @color_pair, nil) else #$log.debug "MENU SUBMENU menu highlight: #{text} #{@row} #{@col}, PW #{@parent.width} " acolor = tf ? $datacolor : $reversecolor att = tf ? Ncurses::A_REVERSE : Ncurses::A_NORMAL #@parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_NORMAL, color, nil) #@parent.window.mvchgat(y=@row, x=1, @parent.width, Ncurses::A_NORMAL, color, nil) # above line did not work with vt100/vt200 next does # @parent.window.mvchgat(y=@row, x=1, @parent.width, att, $reversecolor, nil) # changed 2011 2011-09-24 @parent.window.mvchgat(y=@row, x=1, @parent.width, att, @color_pair, nil) @parent.window.wrefresh end end
# File lib/canis/core/widgets/rmenu.rb, line 246 def insert_separator ix @items.insert ix, MenuSeparator.new end
add item method which could be used from blocks add 2010-09-10 12:20 simplifying
# File lib/canis/core/widgets/rmenu.rb, line 231 def item text, mnem=nil, &block #$log.debug "YYYY inside M: menuitem text #{text} " m = MenuItem.new text, mnem, &block add m return m end
generate an item list at runtime for this menu
# File lib/canis/core/widgets/rmenu.rb, line 267 def item_list *args, &block $log.debug ">>>item_list : #{@text} " @item_list = block if block_given? @item_list_args = args end
# File lib/canis/core/widgets/rmenu.rb, line 415 def on_enter # menu.on_enter #$log.debug "menu onenter: #{text} #{@row} #{@col} " # call parent method. XXX #if @parent.is_a? Canis::MenuBar #acolor = get_color($datacolor, @bgcolor, @color) #@parent.window.printstring( @row, @col, " %s " % text, acolor) #else highlight #end if !@window.nil? #and @parent.selected #$log.debug "menu onenter: #{text} calling window,show" @window.show select_item 0 elsif @parent.is_a? Canis::MenuBar and @parent.selected # only on the top level do we open a window if a previous one was opened #$log.debug "menu onenter: #{text} calling repaint CLASS: #{@parent.class}" # repaint create_window end end
# File lib/canis/core/widgets/rmenu.rb, line 435 def on_leave # menu.on_leave #$log.debug "menu onleave: #{text} #{@row} #{@col} " # call parent method. XXX @color_pair ||= get_color($reversecolor, @color, @bgcolor) if @parent.is_a? Canis::MenuBar # @parent.window.printstring( @row, @col, " %s " % text, $reversecolor) # changed 2011 2011-09-24 @parent.window.printstring( @row, @col, " %s " % text, @color_pair) @window.hide if !@window.nil? else #$log.debug "MENU SUBMEN. menu onleave: #{text} #{@row} #{@col} " # parent is a menu highlight false #@parent.current_menu.pop #@@menus.pop #destroy end end
added 2009-01-21 12:09 NEW
# File lib/canis/core/widgets/rmenu.rb, line 259 def remove n if n.is_a? Integer @items.delete_at n else @items.delete n end end
user has clicked down, we shoud display items DRAW menuitems
# File lib/canis/core/widgets/rmenu.rb, line 316 def repaint # menu.repaint # OMG will not print anything if no items ! # When we do item generation this list will be empty #return if @items.nil? or @items.empty? # commented 2011-09-24 NEWMENU #$log.debug "menu repaint: #{text} row #{@row} col #{@col} " @color_pair = get_color($reversecolor, @color, @bgcolor) if !@parent.is_a? Canis::MenuBar @parent.window.printstring( @row, 0, "|%-*s>|" % [@width-1, text], @color_pair) @parent.window.refresh end if @window.nil? #create_window else @window.show select_item 0 @window.refresh end end
recursive if given one not enabled goes to next enabled
# File lib/canis/core/widgets/rmenu.rb, line 336 def select_item ix0 return if @items.nil? or @items.empty? #$log.debug "insdie select item : #{ix0} active: #{@active_index}" if !@active_index.nil? @items[@active_index].on_leave end previtem = @active_index @active_index = ix0 if @items[ix0].enabled @items[ix0].on_enter else #$log.debug "insdie sele nxt item ENABLED FALSE : #{ix0}" if @active_index > previtem select_next_item else select_prev_item end end @window.refresh end
If multi-column menuitems then try going to a left item (prev column same row) NOTE It should only come here if items are open, otherwise row and col will be blank. NOTE active_index nil means no items open
# File lib/canis/core/widgets/rmenu.rb, line 380 def select_left_item return :UNHANDLED if @items.nil? or @items.empty? or @active_index.nil? index = nil crow = @items[@active_index].row ccol = @items[@active_index].col @items.each_with_index { |e, i| index = i if e.row == crow && e.col < ccol } if index select_item index else return :UNHANDLED end end
# File lib/canis/core/widgets/rmenu.rb, line 356 def select_next_item return if @items.nil? or @items.empty? #$log.debug "insdie sele nxt item : #{@active_index}" @active_index = -1 if @active_index.nil? if @active_index < @items.length-1 select_item @active_index + 1 else # select_item 0 end end
# File lib/canis/core/widgets/rmenu.rb, line 366 def select_prev_item return if @items.nil? or @items.empty? #$log.debug "insdie sele prv item : #{@active_index}" if @active_index > 0 select_item @active_index - 1 else #select_item @items.length-1 end end
@since 1.3.1 2011-09-24 If multi-column menuitems then try going to a right item (next column same row) Only if items are open, not from a menubar menu
# File lib/canis/core/widgets/rmenu.rb, line 395 def select_right_item return :UNHANDLED if @items.nil? or @items.empty? or @active_index.nil? crow = @items[@active_index].row ccol = @items[@active_index].col #alert "inside select right with #{@items.size} #{@items[@active_index].text}: items. r #{crow} col #{ccol} " index = nil @items.each_with_index { |e, i| $log.debug " select_right #{e.row} == #{crow} , #{e.col} > #{ccol} " if $log.debug? if e.row == crow && e.col > ccol index = i $log.debug "YYY select_right #{e.row} == #{crow} , #{e.col} > #{ccol} FOUND #{i} " if $log.debug? break end } if index select_item index else return :UNHANDLED end end
menu
# File lib/canis/core/widgets/rmenu.rb, line 656 def show # menu.show #$log.debug "show (menu) : #{@text} " if @window.nil? create_window #@col+@width end @window.show select_item 0 end
# File lib/canis/core/widgets/rmenu.rb, line 218 def to_s @text end