[Borges-users] TreeMenu Component

Kaspar Schiess eule at space.ch
Wed Apr 14 21:08:15 EDT 2004


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello all,

I have developed a small component that could be useful to everyone:
Rendering a main menu in hierarchical tree form.

Here's how to use this:

class MyComponent < Borges::Component

~  def initialize
~    @treemenu = Borges::TreeMenu.new
~    @treemenu.add('First Item') do inform('first item') end
~    s = @treemenu.add('Second Item') do inform('second item') end

~    s.add('First Child')
~    s.add('Second Child') do inform('second child') end
~  end

~  def render_content_on(r)
~    r.table do
~      r.table_row do
~        r.table_data do
~          r.render(@treemenu)
~        end
~        r.table_data do
~          # render content area here
~        end
~      end
~    end
~  end
end

Will result in a page that has two parts, left part will contain a tree
menu that looks like this:

First Item
Second Item
~  First Child
~  Second Child

Your comment is welcome.

kaspar - code philosopher

- -- stolen off the net --
The one day you'd sell your birthright for something, birthrights are
a glut.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFAfX4PFifl4CA0ImQRAhMBAKCQ0adCIzb8+sg40RFqt6otSAmnxQCggPQy
FDWI1h9kZ9z0uR3rl9b1rwc=
=fpyb
-----END PGP SIGNATURE-----
-------------- next part --------------

# A tree menu is a menu that has different levels of display. 
# This for example could be a tree menu: 
# 
#  First Item 
#    First Subitem 
#    Second Subitem
#  Second Item
#
# Such a menu would be constructed by the following code:  
# 
# n1 = tree.add('First Item') 
#   tree.add('First Subitem', n1) 
#   tree.add('Second Subitem', n1)
# tree.add('Second Item')
# 
# (Ident reflect meaning.) Now adding actions to that: 
# 
# n1 = tree.add('First Item') do puts 'first' end 
#   tree.add('First Subitem', n1) 
#   tree.add('Second Subitem', n1) do puts 'second sub' end
# tree.add('Second Item')
#
# Outputting the not so useful 'first' and 'second sub' strings
# to the console when clicked. 
# 
# The tree menu is rendered inside a component like this (of course):
# 
# def render_content_on(r)
#   ... 
#   r.render(@treemenu)  # assuming your tree menu sits in @treemenu
#   ...
# end
class Borges::TreeMenu
  attr_reader :root, :selection
  
  TreeItem = Struct.new('TreeItem', 
    :label, :block, :subs, :parent, :container
  )
  
  # support lazy adding
  class TreeItem 
    def add(text, &block)
      self.container.add(text, self, &block)
    end
    
    def clear
      self.container.clear(self)
    end
  end
  
  def initialize
    @root = TreeItem.new( 
      'root', nil, [], nil, self
    )
      
    @selection = nil
  end
  
  def add(text, node=self.root, &block)
    child = TreeItem.new(
      text, block, [], node, self
    )
    
    node.subs << child
    child
  end
  
  def clear(node=self.root)
    node.subs.clear
  end
  
  def is_parent_of?(node, parent)
    until node.nil? 
      return true if node == parent
      node = node.parent
    end
    false
  end
  
  def item_action(subnode)
    @selection = subnode
    # node requested action 
    if subnode.block 
      if subnode.block.arity == 0
        subnode.block.call
      else 
        subnode.block.call(subnode)
      end
    end
  end
  private :item_action
  
  def render_on(r, node=self.root, level=1)
    r.css_class "menu#{level}"
    r.div do 
      node.subs.each do |subnode|
        if is_parent_of?(@selection, subnode)
          if @selection == subnode 
            r.text(subnode.label)
          else 
            r.anchor(subnode.label) do item_action(subnode) end
          end
          r.break
          
          self.render_on(r, subnode, level+1)
        else 
          # draw node that has not yet been selected
          r.anchor(subnode.label) do item_action(subnode) end
          r.break
        end
      end  # node.each
    end  # div
  end
end


More information about the Borges-users mailing list