module CellGrid
  def cell_array
    @cell_array || @cell_array = []
  end
  def row_array(row)
    cell_array[row] || cell_array[row] = [] 
  end
  def rows
    cell_array.size
  end
  def cols
    @cols || @cols = cell_array.collect{|row_array| row_array.size }.max
  end
  def [](row,col)
    row_array(row)[col]
  end
  def []= (row,col,item)
    @cols = nil
    row_array(row)[col] = item
  end
  def layout
    item_width  = self.width  / self.cols
    item_height = self.height / self.rows
    rows.times{|row|
      cols.times{|col|
        next unless item = self[row,col]
        item.width  = item_width
        item.height = item_height
        item.left   = item_width  * col
        item.top    = item_height * row
      }
    }
  end
end

require "Phi"

module CellItem
  attr :row,true
  attr :col,true
end

form = Phi::Form.new

panel = Phi::Panel.new form
panel.extend CellGrid
panel.align = Phi::AL_CLIENT

btn_click=proc{|sender| 
  form.caption = "#{sender.row} : #{sender.col} clicked"
  if sender.caption != "o"
    sender.caption = "o"
  else
    sender.caption = "x"
  end
}

10.times{|r|
  20.times{|c|
    panel[r,c] = btn = Phi::SpeedButton.new( panel, :xx , "!" )
    btn.extend CellItem
    btn.row = r
    btn.col = c
    btn.on_click = btn_click
  }
}

form.on_resize = proc{ panel.layout }
form.show
Phi.mainloop
