#!/usr/bin/env ruby

require "fox"
require "date"

include Fox

class TableWindow < FXMainWindow

  def initialize(app)
    # Call the base class initializer first
    super(app, "Table Widget Test", nil, nil, DECOR_ALL, 0, 0, 0, 0)

    # Tooltip
    tooltip = FXTooltip.new(getApp())
    
    # Icon used in some cells
    penguinicon = FXGIFIcon.new(getApp(), File.open(File.join('icons', 'penguin.gif'), 'rb').read, 0, IMAGE_ALPHAGUESS)
    
    # Menubar
    menubar = FXMenubar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
    
    # Separator
    FXHorizontalSeparator.new(self,
      LAYOUT_SIDE_TOP|LAYOUT_FILL_X|SEPARATOR_GROOVE)
  
    # Contents
    contents = FXVerticalFrame.new(self,
      LAYOUT_SIDE_TOP|FRAME_NONE|LAYOUT_FILL_X|LAYOUT_FILL_Y)
    
    frame = FXVerticalFrame.new(contents,
      FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y)
    frame.padLeft, frame.padRight = 0, 0
    frame.padTop, frame.padBottom = 0, 0
  
    # Table
    @table = FXTable.new(frame, 20, 8, nil, 0,
      TABLE_COL_SIZABLE|TABLE_ROW_SIZABLE|LAYOUT_FILL_X|LAYOUT_FILL_Y,
      0,0,0,0, 2,2,2,2)
    @table.setTableSize(50, 14)
    @table.leadingRows = 1
    @table.leadingCols = 1
    @table.trailingRows = 1
    @table.trailingCols = 1
  
    # Initialize first & last fixed rows
    (1..12).each { |c|
      @table.setItemText(0,  c, Date::MONTHNAMES[c])
      @table.setItemText(49, c, Date::MONTHNAMES[c])
      @table.getItem(0, c).setButton(true)
    }
    @table.getItem(0, 0).setButton(true)
    @table.getItem(0, 13).setButton(true)
  
    # Initialize first & last fixed columns
    (1..48).each { |r|
      @table.setItemText(r,  0, r.to_s)
      @table.setItemText(r, 13, r.to_s)
      @table.getItem(r, 0).setButton(true)
    }
    @table.getItem(49, 0).setButton(true)
    @table.getItem(4, 0).setButton(true)
  
    # Initialize scrollable part of table
    (1..48).each { |r|
      (1..12).each { |c|
        @table.setItemText(r, c, "r:#{r} c:#{c}")
      }
    }
    
    @table.setItemText(10, 10, "This is multi-\nline text")
    @table.setRowHeight(10, 35)
    @table.getItem(10, 10).justify = 0  # centered text

    @table.setItem(3, 3, nil)
    @table.setItem(5, 6, @table.getItem(5, 5))
    @table.setItem(5, 7, @table.getItem(5, 5))
    @table.setItemText(5, 5, "Spanning Item")
    @table.getItem(5, 5).justify = 0    # centered text
    
    @table.getItem(9, 9).borders = FXTableItem::TBORDER|FXTableItem::LBORDER|FXTableItem::BBORDER
    @table.getItem(9, 10).borders = FXTableItem::TBORDER|FXTableItem::RBORDER|FXTableItem::BBORDER
    
    @table.getItem(40, 13).borders = FXTableItem::LBORDER|FXTableItem::TBORDER|FXTableItem::RBORDER|FXTableItem::BBORDER
    @table.getItem(49, 13).borders = FXTableItem::LBORDER|FXTableItem::TBORDER|FXTableItem::RBORDER|FXTableItem::BBORDER
    @table.getItem(5, 0).borders = FXTableItem::LBORDER|FXTableItem::TBORDER|FXTableItem::RBORDER|FXTableItem::BBORDER
    
    @table.getItem(6, 6).icon = penguinicon
    @table.getItem(6, 6).iconPosition = FXTableItem::ABOVE  # icon above the text
    @table.getItem(6, 6).justify = 0    # centered text
    
    @table.getItem(3, 4).stipple = STIPPLE_CROSSDIAG
    
    # Some table events
    @table.connect(SEL_SELECTED) { |sender, sel, tableRange|
      puts "SEL_SELECTED fm.row=#{tableRange.fm.row}, fm.col=#{tableRange.fm.col} to.row=#{tableRange.to.row}, to.col=#{tableRange.to.col}"
    }
    @table.connect(SEL_DESELECTED) { |sender, sel, tableRange|
      puts "SEL_DESELECTED fm.row=#{tableRange.fm.row}, fm.col=#{tableRange.fm.col} to.row=#{tableRange.to.row}, to.col=#{tableRange.to.col}"
    }
    @table.connect(SEL_INSERTED) { |sender, sel, tableRange|
      puts "SEL_INSERTED fm.row=#{tableRange.fm.row}, fm.col=#{tableRange.fm.col} to.row=#{tableRange.to.row}, to.col=#{tableRange.to.col}"
    }
    @table.connect(SEL_DELETED) { |sender, sel, tableRange|
      puts "SEL_DELETED fm.row=#{tableRange.fm.row}, fm.col=#{tableRange.fm.col} to.row=#{tableRange.to.row}, to.col=#{tableRange.to.col}"
    }
    @table.connect(SEL_CHANGED) { |sender, sel, tablePos|
      puts "SEL_CHANGED row=#{tablePos.row}, col=#{tablePos.col}"
    }
    @table.connect(SEL_COMMAND) { |sender, sel, ptr|
      puts "SEL_COMMAND ptr=#{ptr}"
    }
    @table.connect(SEL_CLICKED) { |sender, sel, ptr|
      puts "SEL_CLICKED ptr=#{ptr}"
    }
    
    # File Menu
    filemenu = FXMenuPane.new(self)
    FXMenuCommand.new(filemenu, "&Quit\tCtl-Q", nil, getApp(), FXApp::ID_QUIT)
    FXMenuTitle.new(menubar, "&File", nil, filemenu)
    
    # Options Menu
    tablemenu = FXMenuPane.new(self)
    FXMenuCommand.new(tablemenu, "Horizontal grid", nil,
      @table, FXTable::ID_HORZ_GRID)
    FXMenuCommand.new(tablemenu, "Vertical grid", nil,
      @table, FXTable::ID_VERT_GRID)
    FXMenuTitle.new(menubar, "&Options", nil, tablemenu)
    
    # Manipulations Menu
    manipmenu = FXMenuPane.new(self)
    FXMenuCommand.new(manipmenu, "Delete Column\tCtl-C", nil,
      @table, FXTable::ID_DELETE_COLUMN)
    FXMenuCommand.new(manipmenu, "Delete Row\tCtl-R", nil,
      @table, FXTable::ID_DELETE_ROW)
    FXMenuCommand.new(manipmenu, "Insert Column\tCtl-Shift-C", nil,
      @table, FXTable::ID_INSERT_COLUMN)
    FXMenuCommand.new(manipmenu, "Insert Row\tCtl-Shift-R", nil,
      @table, FXTable::ID_INSERT_ROW)
    FXMenuCommand.new(manipmenu, "Resize table...").connect(SEL_COMMAND, method(:onCmdResizeTable))
    FXMenuTitle.new(menubar, "&Manipulations", nil, manipmenu)
    
    # Selection Menu
    selectmenu = FXMenuPane.new(self)
    FXMenuCommand.new(selectmenu, "Select All", nil,
      @table, FXTable::ID_SELECT_ALL)
    FXMenuCommand.new(selectmenu, "Select Cell", nil,
      @table, FXTable::ID_SELECT_CELL)
    FXMenuCommand.new(selectmenu, "Select Row", nil,
      @table, FXTable::ID_SELECT_ROW)
    FXMenuCommand.new(selectmenu, "Select Column", nil,
      @table, FXTable::ID_SELECT_COLUMN)
    FXMenuCommand.new(selectmenu, "Deselect All", nil,
      @table, FXTable::ID_DESELECT_ALL)
    FXMenuTitle.new(menubar, "&Selection", nil, selectmenu)
  end

  # Resize the table
  def onCmdResizeTable(sender, sel, ptr)
    # Create an empty dialog box
    dlg = FXDialogBox.new(self, "Resize Table")

    # Set up its contents
    frame = FXHorizontalFrame.new(dlg, LAYOUT_FILL_X|LAYOUT_FILL_Y)
    FXLabel.new(frame, "Rows:", nil, LAYOUT_SIDE_LEFT|LAYOUT_CENTER_Y)
    rows = FXTextField.new(frame, 5, nil, 0,
      JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_LEFT|LAYOUT_CENTER_Y)
    FXLabel.new(frame, "Columns:", nil, LAYOUT_SIDE_LEFT|LAYOUT_CENTER_Y)
    cols = FXTextField.new(frame, 5, nil, 0,
      JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_LEFT|LAYOUT_CENTER_Y)
    FXButton.new(frame, "Cancel", nil, dlg, FXDialogBox::ID_CANCEL,
      FRAME_RAISED|FRAME_THICK|LAYOUT_SIDE_LEFT|LAYOUT_CENTER_Y)
    FXButton.new(frame, "  OK  ", nil, dlg, FXDialogBox::ID_ACCEPT,
      FRAME_RAISED|FRAME_THICK|LAYOUT_SIDE_LEFT|LAYOUT_CENTER_Y)

    # Initialize the text fields' contents
    oldnr, oldnc = @table.numRows, @table.numCols
    rows.text = oldnr.to_s
    cols.text = oldnc.to_s

    # FXDialogBox#execute will return non-zero if the user clicks OK
    if dlg.execute != 0
      nr, nc = rows.text.to_i, cols.text.to_i
      nr = 0  if nr < 0
      nc = 0  if nc < 0
      @table.setTableSize(nr, nc)
      (0...nr).each { |r|
        (0...nc).each { |c|
          if (r > oldnr) || (c > oldnc)
            @table.setItemText(r, c, "r:#{r+1} c:#{c+1}")
          end
        }
      }
    end
    return 1
  end

  # Create and show this window
  def create
    super
    show(PLACEMENT_SCREEN)
  end
end

# Start the whole thing
if __FILE__ == $0
  # Make application
  application = FXApp.new("TableApp", "FoxTest")
  
  # Open display
  application.init(ARGV)
  
  # Make window
  TableWindow.new(application)
  
  # Create app
  application.create
  
  # Run
  application.run
end
