'''
### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###

      CellData, CellCoordinate, SpreadsheetData classes API.

      Hans Vangheluwe & Jean-Sébastien Bolduc
      Modelling, Simulation and Design Lab
      School of Computer Science 
      McGill University

      last modified: 01/21/02

### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
'''


# Types of objects that can be stored in a CellData object
dataTypes = (types.IntType,)

### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
### class CellData


class CellData:
  """
  Encapsulated Integer data
  """

  def __init__(self, value = 0):
    ''' value:Integer ->    --  CellData constructor.

    A TypeError is raised on bad argument.
    '''

  def getValue(self):
    ''' -> :Integer'''

  def setValue(self, value = 0):
    ''' value:Integer ->

    A TypeError is raised on bad argument.
    '''

  def __str__(self):
    ''' -> :String 
    
    Return the string representation of the object value (Integer).
    '''

### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
### class CellCoordinate

class CellCoordinate:
  """
  Encapsulated coordinates of cells in a spreadsheet.

  Note: might in the future want to implement "coordinate arithmetic"
  by means of __add__ etc.
  """

  def __init__(self, row = 1, column = 1):
    ''' row:PositiveInteger, column:PositiveInteger -> 
    
    CellCoordinate constructor.
    A KeyError is raised on bad arguments.
    '''

  def getRow(self):
    ''' -> :Integer'''

  def getColumn(self):
    ''' -> :Integer'''

  def setRow(self, row = 1):
    '''row:PositiveInteger -> 

    A KeyError is raised on bad argument.
    '''

  def setColumn(self, column = 1):
    '''column:PositiveInteger ->

    A KeyError is raised on bad argument.
    '''

  def __str__(self):
    ''' -> :String

    Return the string representation of the cell coordinate.
    Example: with row=2, column=88, __str__ will return <CellCoordinate:2,88>
    '''

### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
### class SpreadsheetData

class SpreadsheetData:
  """
  Encapsulates a dynamically sized spreadsheet structure
  containing CellData data and indexed by CellCoordinate coordinates.
  """
  def __init__(self):
    ''' __init__() ->  -- SpreadsheetData constructor.'''

  def __setitem__(self, coord, data):
    '''coord:CellCoordinate, data:CellData ->

    Update the content of cell indexed by ``coord'' with ``data''.
    A KeyError is raised on bad coordinate,
    A TypeError is raised on bad value.
    Example use: sd[CellCoordinate(3,4)] = CellData(33)
    '''

  def __getitem__(self, coord):
    '''coord:CellCoordinate -> :CellData | None

    Return the content of a cell indexed by ``coord''
    (return None if the cell is empty).
    A KeyError is raised on bad coordinate.
    Example use: sd[CellCoordinate(3,4)]
    '''

  def __delitem__(self, coord):
    '''coord:CellCoordinate ->

    Empty the cell indexed by ``coord''.
    A KeyError is raised on bad coordinate.
    Example use: del sd[CellCoordinate(3,4)]
    '''

  def getLU(self):
    ''' -> :CellCoordinate | None

    Return a CellCoordinate containing the 
    Left-most non-empty column, and Upper-most non-emtpy row.
    Return None in case of an empty spreadsheet
    '''

  def getRB(self):
    ''' -> :CellCoordinate | None

    Return a CellCoordinate containing the Right-most non-empty column,
    and Bottom-most non-emtpy row.
    Return None in case of an empty spreadsheet
    '''

  def __str__(self):
    ''' -> :String

    Return the string representation of the SpreadSheet.
    This looks like a table of values with spaces for empty cells.
    The row and column indexes are also shown.
    '''

