kwicher and many others are using Hackety Hack to learn how to code.

Hackety Hack is a free program for Windows, Mac OS X and Linux that can teach you how to make games, applications and more and share those programs with your friends. You can ask other budding programmers questions and follow them to see what code they're working on through the Hackety Hack website.

Sign up Learn More

menu by kwicher

# Krzysztof B. Wicher 2008 version v0.6
# 
# Menu = Widget emulating pop-up menu with a given ":title" and ":width" and
# at the given coordinates (":left", ":top") in the current slot.
# One can choose if the menu will pop-up upon hoovering on -
# :pop_up_on_click=>false or upon clicking on the title - :pop_up_on_click=>true
# One can choose to leave menu open upon moving mouse out - :pop_out_on_leave=>false 
# or to hide it - :pop_out_on_leave=>false
# Menu items are loaded from the ":items" array. One can also specify the items in the menu
# which should be inactive/unresposive to the hoovering and clicking ":blocked" array.
# Moreover, one can dinamically change the ":items" and ":blocked" using attr_accessors. 
# Method returns the "item" clicked.
# ":state" attr-accessor allows to disable (:disabled) and enable (:enable) the menu
# State can be toggled by using "toggle_state" method.
# For simplicity method hard-codes menu colors

class Menu < Shoes::Widget
  attr_accessor :items, :blocked, :state
  def set_blocked(blocked)
    @blocked=blocked
  end
  def toggle_state
    case @state
    when :enabled then @state=:disabled
    when :disabled then @state=:enabled
    end
  end
  def initialize opts={}
    @state=:enabled
    @title=opts[:title]
    @items=opts[:items]
    @blocked=opts[:blocked]
    @leavee=opts[:pop_out_on_leave]
    @width=opts[:width]
    hor_mult=0
    vert_mult=0
    showed=false
    clicke=opts[:pop_up_on_click]
    case opts[:orientation]
    when :ver then vert_mult=25
    when :hor then hor_mult=@width
    end
    nostroke
    fill yellow
    m=[]
    flot = flow :top=>0, :left=>0, :width=>@width-1, :height=>24 do
      background yellow
      para @title, :align=>'center'
      leave do
        flot.clear do
          background yellow
          para @title, :align=>'center'
        end
      end 
    end
    fl=stack :left=>0, :top=>0, :width=>(hor_mult+1)*@items.size+@width, :height=>(vert_mult+1)*@items.size+25 do      
      leave do    
        if showed
          if @leavee==true
            m.each_index do|l| 
              m[l].clear
              m[l].remove
            end
            showed=false
          end
        end
      end
  # IF POP-UP BY CLICKING
      if clicke==true 
        flot.click do
          if @state==:enabled
            flot.hover do
              flot.clear do
                background orange
                para @title, :align=>'center'
              end
            end
            if showed==false
              showed=true
              @items.each_with_index do |i,l|
                m[l]=stack :top=>vert_mult*(l+1),:left=>hor_mult*(l+1),:width=>@width-1,:height=>24 do 
                  if not @blocked.include?(i)
                    background red
                    para @items[l]
                  else
                    background gray
                    para @items[l]
                  end
                end      
                m[l].hover do
                  if not @blocked.include?(i)
                    m[l].clear do
                      background green
                      para @items[l]
                    end
                  end
                end
                m[l].leave do
                  if not @blocked.include?(i)
                    m[l].clear do
                      background red
                      para @items[l]
                    end
                  end
                end
                m[l].click do
                  if not @blocked.include?(i)
                    showed=false
                    res=i
                    m.each{|i| i.remove}   
                    yield res
                  end
                end
              end
            else 
              m.each{|i| i.remove}
              showed=false
            end
          end
        end
   #IF POP-UP BY HOVER
      elsif clicke==false 
        
        flot.hover do
          if @state==:enabled
            flot.clear do
              background orange
              para @title, :align=>'center'
            end
            showed=true
            @items.each_with_index do |i,l|
              m[l]=stack :top=>(vert_mult*(l+1)),:left=>hor_mult*(l+1),:width=>@width-1,:height=>24 do 
                if not @blocked.include?(i)
                  background red
                  para @items[l]
                else
                  background gray
                  para @items[l]
                end
              end      
              m[l].hover do
                if not @blocked.include? i
                  m[l].clear do
                    background green
                    para @items[l]
                  end
                end
              end
              m[l].leave do
                if not @blocked.include?(i)
                  m[l].clear do
                    background red
                    para @items[l]
                  end
                end
              end
              m[l].click do
                if not @blocked.include?(i)
                  res=i 
                  m.each{|i|
                    i.clear
                    i.remove}
                  showed=false
                  yield res
                end
              end
              m[l].show
            end
          end
        end
      end
    end
  end   
end

# TEST APPLICATION

Shoes.app :width=>450, :height=>350 do  
  stack do
    subtitle "Menu test"
    @t=edit_line "Click the menu"
    items=["item1","item2", "item3"]
    items1=["it1","it2", "it3", "it4"]
    m1=menu(:title=>"Menu1",:left=>80, :top=>100, :width=>70, :items=>items,:blocked=>["item2"], :orientation=>:ver, :pop_up_on_click=>true, :pop_out_on_leave=>false){|x| @t.text=x}    
    m2=menu(:title=>"Menu2",:left=>10, :top=>130, :width=>70, :items=>items1, :blocked=>["it3"], :orientation=>:hor, :pop_up_on_click=>false, :pop_out_on_leave=>true){|x| alert "You clicked: #{x}"}
    button "Close", :top=>180, :left=> 200 do
      close 
    end
    button "Change Menu2 items", :top=>220, :left=> 200 do
      m2.items=["it3", "it4"]
    end
    button "Change back Menu2 items", :top=>260, :left=> 200 do
      m2.items=["it1","it2", "it3", "it4"]
    end
    button "Toggle enable/disable Menu2", :top=>300, :left=> 200 do
      m2.toggle_state
    end
  end
end