/***********************************************************************
 * FXRuby -- the Ruby language bindings for the FOX GUI toolkit.
 * Copyright (c) 2001-2003 by J. Lyle Johnson. All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * For further information please contact the author by e-mail
 * at "lyle@users.sourceforge.net".
 ***********************************************************************/

class FXTable;

// Default cell margin
enum { DEFAULT_MARGIN = 2 };


/// Table options
enum {
  TABLE_COL_SIZABLE     = 0x00100000,   /// Columns are resizable
  TABLE_ROW_SIZABLE     = 0x00200000,   /// Rows are resizable
  TABLE_HEADERS_SIZABLE = 0x00400000,   /// Headers are sizable
  TABLE_NO_COLSELECT    = 0x00900000,   /// Disallow column selections
  TABLE_NO_ROWSELECT    = 0x01000000    /// Disallow row selections
  };


// Position in table
struct FXTablePos {
  FXTablePos();
  FXint  row;
  FXint  col;
  ~FXTablePos();
  };
  

// Range of table cells
struct FXTableRange {
  FXTableRange();
  FXTablePos fm;
  FXTablePos to;
  ~FXTableRange();
  };


/// Item in table
class FXTableItem : public FXObject {
protected:
  FXString    label;
  FXIcon     *icon;
  void       *data;
  FXuint      state;
protected:
  FXTableItem():icon(NULL),data(NULL),state(0){}
  FXint textWidth(const FXTable* table) const;
  FXint textHeight(const FXTable* table) const;
  virtual void draw(const FXTable* table,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const;
  virtual void drawBorders(const FXTable* table,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const;
  virtual void drawContent(const FXTable* table,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const;
  virtual void drawPattern(const FXTable* table,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const;
  virtual void drawBackground(const FXTable* table,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const;
protected:
  FXTableItem();
protected:
  enum{
    SELECTED   = 0x00000001,
    FOCUS      = 0x00000002,
    DISABLED   = 0x00000004,
    DRAGGABLE  = 0x00000008,
    RESERVED1  = 0x00000010,
    RESERVED2  = 0x00000020,
    ICONOWNED  = 0x00000040
    };
public:
  enum{    
    RIGHT      = 0x00002000,      /// Align on right
    LEFT       = 0x00004000,      /// Align on left
    CENTER_X   = 0,               /// Align centered horizontally (default)
    TOP        = 0x00008000,      /// Align on top
    BOTTOM     = 0x00010000,      /// Align on bottom
    CENTER_Y   = 0,               /// Align centered vertically (default)
    BEFORE     = 0x00020000,      /// Icon before the text
    AFTER      = 0x00040000,      /// Icon after the text
    ABOVE      = 0x00080000,      /// Icon above the text
    BELOW      = 0x00100000,      /// Icon below the text
    LBORDER    = 0x00200000,      /// Draw left border
    RBORDER    = 0x00400000,      /// Draw right border
    TBORDER    = 0x00800000,      /// Draw top border
    BBORDER    = 0x01000000       /// Draw bottom border
    };
public:
  %extend {
    FXTableItem(const FXString& text,FXIcon* ic=NULL,void* ptr=NULL){
      return new FXRbTableItem(text,ic,ptr);
      }
    }

  const FXString& getText() const;
  FXIcon* getIcon() const;

  %extend {
    void setData(VALUE ptr){
      self->setData(reinterpret_cast<void*>(ptr));
      }
    VALUE getData() const {
      return self->getData() ? reinterpret_cast<VALUE>(self->getData()) : Qnil;
      }
  }
  FXbool hasFocus() const;
  FXbool isSelected() const;
  FXbool isEnabled() const;
  FXbool isDraggable() const;
  void setJustify(FXuint justify);
  FXuint getJustify() const;
  void setIconPosition(FXuint mode);
  FXuint getIconPosition() const;
  void setBorders(FXuint borders);
  FXuint getBorders() const;
  void setStipple(FXStipplePattern pattern);
  FXStipplePattern getStipple() const;
  FXuint isIconOwned() const;
  virtual ~FXTableItem();
  };


DECLARE_FXOBJECT_VIRTUALS(FXTableItem)
DECLARE_FXTABLEITEM_VIRTUALS(FXTableItem)

// Enforce row numbers that are within bounds 0 <= row < numRows
%typemap(check) FXint TABLE_ROW_INDEX {
  if ($1 < 0 || $1 >= arg1->getNumRows()) {
    rb_raise(rb_eIndexError, "table row out of bounds");
  }
}

// Enforce row numbers that are within bounds 0 <= row <= numRows
%typemap(check) FXint TABLE_ROW_ALL {
  if ($1 < 0 || $1 > arg1->getNumRows()) {
    rb_raise(rb_eIndexError, "table row out of bounds");
  }
}

// Enforce row = 0 or row = 1 only
%typemap(check) FXint ROW_ZERO_OR_ONE {
  if ($1 != 0 && $1 != 1) {
    rb_raise(rb_eIndexError, "table row out of bounds");
  }
}

// Special for removeRows()
%typemap(check) (FXint row,FXint nr) {
  if ($1 < 0 || $1 + $2 > arg1->getNumRows()) {
    rb_raise(rb_eIndexError,"table row out of bounds");
  }
}

// Enforce column numbers that are within bounds 0 <= column < numColumns
%typemap(check) FXint TABLE_COLUMN_INDEX {
  if ($1 < 0 || $1 >= arg1->getNumColumns()) {
    rb_raise(rb_eIndexError, "table column out of bounds");
  }
}

// Enforce column numbers that are within bounds 0 <= column <= numColumns
%typemap(check) FXint TABLE_COLUMN_ALL {
  if ($1 < 0 || $1 > arg1->getNumColumns()) {
    rb_raise(rb_eIndexError, "table column out of bounds");
  }
}

// Enforce column = 0 or column = 1 only
%typemap(check) FXint COLUMN_ZERO_OR_ONE {
  if ($1 != 0 && $1 != 1) {
    rb_raise(rb_eIndexError, "table column out of bounds");
  }
}

// Special for removeColumns()
%typemap(check) (FXint col,FXint nc) {
  if ($1 < 0 || $1 + $2 > arg1->getNumColumns()) {
    rb_raise(rb_eIndexError,"table column out of bounds");
  }
}

%apply FXint TABLE_ROW_INDEX { FXint row, FXint r };
%apply FXint TABLE_COLUMN_INDEX { FXint col, FXint c };

/// Table Widget
class FXTable : public FXScrollArea {
public:
  static FXDragType csvType;
  static const FXchar csvTypeName[];
public:
  long onPaint(FXObject*,FXSelector,void* PTR_EVENT);
  long onFocusIn(FXObject*,FXSelector,void* PTR_EVENT);
  long onFocusOut(FXObject*,FXSelector,void* PTR_EVENT);
  long onMotion(FXObject*,FXSelector,void* PTR_EVENT);
  long onKeyPress(FXObject*,FXSelector,void* PTR_EVENT);
  long onKeyRelease(FXObject*,FXSelector,void* PTR_EVENT);
  long onLeftBtnPress(FXObject*,FXSelector,void* PTR_EVENT);
  long onLeftBtnRelease(FXObject*,FXSelector,void* PTR_EVENT);
  long onRightBtnPress(FXObject*,FXSelector,void* PTR_EVENT);
  long onRightBtnRelease(FXObject*,FXSelector,void* PTR_EVENT);
  long onUngrabbed(FXObject*,FXSelector,void* PTR_EVENT);
  long onSelectionLost(FXObject*,FXSelector,void* PTR_EVENT);
  long onSelectionGained(FXObject*,FXSelector,void* PTR_EVENT);
  long onSelectionRequest(FXObject*,FXSelector,void* PTR_EVENT);
  long onClipboardLost(FXObject*,FXSelector,void* PTR_EVENT);
  long onClipboardGained(FXObject*,FXSelector,void* PTR_EVENT);
  long onClipboardRequest(FXObject*,FXSelector,void* PTR_EVENT);
  long onAutoScroll(FXObject*,FXSelector,void* PTR_EVENT);
  long onCommand(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onClicked(FXObject*,FXSelector,void* PTR_EVENT);
  long onDoubleClicked(FXObject*,FXSelector,void* PTR_EVENT);
  long onTripleClicked(FXObject*,FXSelector,void* PTR_EVENT);
  
  // Visual characteristics
  long onCmdHorzGrid(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onUpdHorzGrid(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdVertGrid(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onUpdVertGrid(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  
  // Row/Column manipulations
  long onCmdDeleteColumn(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onUpdDeleteColumn(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdDeleteRow(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onUpdDeleteRow(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdInsertColumn(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdInsertRow(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  
  // Movement
  long onCmdMoveRight(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdMoveLeft(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdMoveUp(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdMoveDown(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdMoveHome(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdMoveEnd(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdMoveTop(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdMoveBottom(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdMovePageDown(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdMovePageUp(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME

  // Mark and extend
  long onCmdMark(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME
  long onCmdExtend(FXObject*,FXSelector,void* PTR_IGNORE); // FIXME

  // Changing Selection
  long onCmdSelectCell(FXObject*,FXSelector,void* PTR_IGNORE);
  long onCmdSelectRow(FXObject*,FXSelector,void* PTR_IGNORE);
  long onCmdSelectColumn(FXObject*,FXSelector,void* PTR_IGNORE);
  long onCmdSelectRowIndex(FXObject*,FXSelector,void* PTR_IGNORE);
  long onCmdSelectColumnIndex(FXObject*,FXSelector,void* PTR_IGNORE);
  long onCmdSelectAll(FXObject*,FXSelector,void* PTR_IGNORE);
  long onCmdDeselectAll(FXObject*,FXSelector,void* PTR_IGNORE);

  // Manipulation Selection
  long onCmdCutSel(FXObject*,FXSelector,void*);
  long onCmdCopySel(FXObject*,FXSelector,void*);
  long onCmdDeleteSel(FXObject*,FXSelector,void*);
  long onCmdPasteSel(FXObject*,FXSelector,void*);
  long onUpdHaveSelection(FXObject*,FXSelector,void*);
public:

  enum {
    ID_HORZ_GRID=FXScrollArea::ID_LAST,
    ID_VERT_GRID,
    ID_DELETE_COLUMN,
    ID_DELETE_ROW,
    ID_INSERT_COLUMN,
    ID_INSERT_ROW,
    ID_SELECT_COLUMN_INDEX,
    ID_SELECT_ROW_INDEX,
    ID_SELECT_COLUMN,
    ID_SELECT_ROW,
    ID_SELECT_CELL,
    ID_SELECT_ALL,
    ID_DESELECT_ALL,
    ID_MOVE_LEFT,
    ID_MOVE_RIGHT,
    ID_MOVE_UP,
    ID_MOVE_DOWN,
    ID_MOVE_HOME,
    ID_MOVE_END,
    ID_MOVE_TOP,
    ID_MOVE_BOTTOM,
    ID_MOVE_PAGEDOWN,
    ID_MOVE_PAGEUP,
    ID_MARK,
    ID_EXTEND,
    ID_CUT_SEL,
    ID_COPY_SEL,
    ID_PASTE_SEL,
    ID_DELETE_SEL,
    ID_LAST
    };

public:
  
  /**
  * Construct a new table.
  * The table is initially empty, and reports a default size based on
  * the scroll areas's scrollbar placement policy.
  */
  %extend {
    FXTable(FXComposite* p,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=0,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=DEFAULT_MARGIN,FXint pr=DEFAULT_MARGIN,FXint pt=DEFAULT_MARGIN,FXint pb=DEFAULT_MARGIN){
      return new FXRbTable(p,tgt,sel,opts,x,y,w,h,pl,pr,pt,pb);
      }
    }
  
  /// Return column header control
  FXHeader* getColumnHeader() const;

  /// Return row header control
  FXHeader* getRowHeader() const;

  /// Change visible rows/columns
  void setVisibleRows(FXint nvrows);
  FXint getVisibleRows() const;
  void setVisibleColumns(FXint nvcols);
  FXint getVisibleColumns() const;
 
  /// Show or hide horizontal grid
  void showHorzGrid(FXbool on=TRUE);

  /// Is horizontal grid shown
  FXbool isHorzGridShown() const;

  /// Show or hide vertical grid
  void showVertGrid(FXbool on=TRUE);
  
  /// Is vertical grid shown
  FXbool isVertGridShown() const;

  /// Get number of rows
  FXint getNumRows() const;

  /// Get number of columns
  FXint getNumColumns() const;

  /// Change top cell margin
  void setMarginTop(FXint pt);

  /// Return top cell margin
  FXint getMarginTop() const;

  /// Change bottom cell margin
  void setMarginBottom(FXint pb);

  /// Return bottom cell margin
  FXint getMarginBottom() const;

  /// Change left cell margin
  void setMarginLeft(FXint pl);

  /// Return left cell margin
  FXint getMarginLeft() const;

  /// Change right cell margin
  void setMarginRight(FXint pr);

  /// Return right cell margin
  FXint getMarginRight() const;

  /**
  * Determine row containing y.
  * Returns -1 if y above first row, and nrows if y below last row;
  * otherwise, returns row in table containing y.
  */
  FXint rowAtY(FXint y) const;
  
  /**
  * Determine column containing x.
  * Returns -1 if x left of first column, and ncols if x right of last column;
  * otherwise, returns columns in table containing x.
  */
  FXint colAtX(FXint x) const;

  /// Return the item at the given index
  FXTableItem *getItem(FXint row,FXint col) const;

  %extend {
    /// Replace the item with a [possibly subclassed] item
    void setItem(FXint row,FXint col,FXTableItem* item,FXbool notify=FALSE){
      if(item!=0 && item->isMemberOf(FXMETACLASS(FXRbTableItem))){
        dynamic_cast<FXRbTableItem*>(item)->owned=TRUE;
        }
      self->setItem(row,col,item,notify);
      }
  }

  /// Scroll to make cell at r,c fully visible
  void makePositionVisible(FXint r,FXint c);
  
  // Return TRUE if item partially visible
  FXbool isItemVisible(FXint r,FXint c) const;

  /**
  * Change column header height mode to fixed or variable.
  * In variable height mode, the column header will size to
  * fit the contents in it.  In fixed mode, the size is
  * explicitly set using setColumnHeaderHeight().
  */
  void setColumnHeaderMode(FXuint hint=LAYOUT_FIX_HEIGHT);

  /// Return column header height mode
  FXuint getColumnHeaderMode() const;

  /**
  * Change row header width mode to fixed or variable.
  * In variable width mode, the row header will size to
  * fit the contents in it.  In fixed mode, the size is
  * explicitly set using setRowHeaderWidth().
  */
  void setRowHeaderMode(FXuint hint=LAYOUT_FIX_WIDTH);

  /// Return row header width mode
  FXuint getRowHeaderMode() const;

  /// Change column header height
  void setColumnHeaderHeight(FXint h);

  /// Return column header height
  FXint getColumnHeaderHeight() const;

  /// Change row header width
  void setRowHeaderWidth(FXint w);

  /// Return row header width
  FXint getRowHeaderWidth() const;

  /// Get column width
  FXint getColumnWidth(FXint col) const;

  /// Get row height
  FXint getRowHeight(FXint row) const;

  %extend {
    FXint getColumnX(FXint colEdge) const {
      if(colEdge<0 || self->getColumnHeader()->getNumItems()<=colEdge){
        rb_raise(rb_eIndexError,"table column out of bounds");
        }
      return self->getColumnX(colEdge);
      }
  
    /// Change Y coordinate of row r
    FXint getRowY(FXint rowEdge) const {
      if(rowEdge<0 || self->getRowHeader()->getNumItems()<=rowEdge){
        rb_raise(rb_eIndexError,"table row out of bounds");
        }
      return self->getRowY(rowEdge);
      }
  }
  
  /// Change default column width
  void setDefColumnWidth(FXint cwidth);
  FXint getDefColumnWidth() const;

  /// Change default row height
  void setDefRowHeight(FXint rheight);
  FXint getDefRowHeight() const;

  /// Return minimum row height
  FXint getMinRowHeight(FXint r) const;

  /// Return minimum column width
  FXint getMinColumnWidth(FXint c) const;

  /// Change column header
  void setColumnText(FXint index,const FXString& text);

  /// Return text of column header at index
  FXString getColumnText(FXint index) const;

  /// Change row header
  void setRowText(FXint index,const FXString& text);

  /// Return text of row header at index
  FXString getRowText(FXint index) const;

  %extend {
    /// Modify cell text
    void setItemText(FXint r,FXint c,const FXString& text){
      FXRbTableItem* item;
      self->setItemText(r,c,text);
      item=dynamic_cast<FXRbTableItem*>(self->getItem(r,c));
      if(item!=0){
        item->owned=TRUE;
        }
      }
  }
  FXString getItemText(FXint r,FXint c) const;

  %extend {  
    /// Modify cell icon
    void setItemIcon(FXint r,FXint c,FXIcon* icon){
      FXRbTableItem* item;
      self->setItemIcon(r,c,icon);
      item=dynamic_cast<FXRbTableItem*>(self->getItem(r,c));
      if(item!=0){
        item->owned=TRUE;
        }
      }
  }
  FXIcon* getItemIcon(FXint r,FXint c) const;
  
  %extend {
    /// Modify cell user-data
    void setItemData(FXint r,FXint c,VALUE ptr){
      FXRbTableItem* item;
      self->setItemData(r,c,reinterpret_cast<void*>(ptr));
      item=dynamic_cast<FXRbTableItem*>(self->getItem(r,c));
      if(item!=0){
        item->owned=TRUE;
        }
      }

    /// Get cell user data
    VALUE getItemData(FXint r,FXint c) const {
      void* ptr=self->getItemData(r,c);
      return (ptr!=0) ? reinterpret_cast<VALUE>(ptr) : Qnil;
      }
  }
  
  %extend {
    /// Extract cells from given range as text.
    VALUE extractText(FXint startrow,FXint endrow,FXint startcol,FXint endcol,FXchar cs='\t',FXchar rs='\n') const {
      FXchar* text;
      FXint size;
      VALUE result;
      if(startrow<0 || startcol<0 || self->getNumRows()<=endrow || self->getNumColumns()<=endcol) rb_raise(rb_eIndexError,"index out of bounds");
      self->extractText(text,size,startrow,endrow,startcol,endcol,cs,rs);
      result=rb_str_new2(text);
      FXFREE(&text);
      return result;
      }

    /// Overlay text over given cell range
    void overlayText(FXint startrow,FXint endrow,FXint startcol,FXint endcol,VALUE str,FXchar cs='\t',FXchar rs='\n'){
      if(startrow<0 || startcol<0 || self->getNumRows()<=endrow || self->getNumColumns()<=endcol) rb_raise(rb_eIndexError,"index out of bounds");
      const FXchar* text=reinterpret_cast<FXchar*>(STR2CSTR(str));
      FXint size=RSTRING(str)->len;
      self->overlayText(startrow,endrow,startcol,endcol,text,size,cs,rs);
      }
  }

  /// Return TRUE if its a spanning cell
  FXbool isItemSpanning(FXint r,FXint c) const;

  %extend {
    /// Repaint cells between grid lines sr,er and grid lines sc,ec
    void updateRange(FXint sr,FXint er,FXint sc,FXint ec) const {
      if(sr<0 || sc<0 || self->getNumRows()<=er || self->getNumColumns()<=ec) rb_raise(rb_eIndexError,"index out of bounds");
      self->updateRange(sr,er,sc,ec);
      }
  }

  /// Repaint cell at r,c
  void updateItem(FXint r,FXint c) const;
  
  /// Enable item
  FXbool enableItem(FXint r,FXint c);

  /// Disable item
  FXbool disableItem(FXint r,FXint c);

  // Is item enabled?
  FXbool isItemEnabled(FXint r,FXint c) const;

  /// Change item justification
  void setItemJustify(FXint r,FXint c,FXuint justify);
  
  /// Return item justification
  FXuint getItemJustify(FXint r,FXint c) const;
  
  /// Change relative position of icon and text of item
  void setItemIconPosition(FXint r,FXint c,FXuint mode);
  
  /// Return relative icon and text position
  FXuint getItemIconPosition(FXint r,FXint c) const;
  
  /// Change item border style
  void setItemBorders(FXint r,FXint c,FXuint borders);
  
  /// Return item border style
  FXuint getItemBorders(FXint r,FXint c) const;
  
  /// Change item background stipple style
  void setItemStipple(FXint r,FXint c,FXStipplePattern pat);
  
  /// Return item background stipple style
  FXStipplePattern getItemStipple(FXint r,FXint c) const;

  /// Get row number of current item
  FXint getCurrentRow() const;

  /// Get column number of current item
  FXint getCurrentColumn() const;

  /// Is this the current item?
  FXbool isItemCurrent(FXint r,FXint c) const;

  /// Change anchor item
  void setAnchorItem(FXint r,FXint c);

  /// Get row number of anchor item
  FXint getAnchorRow() const;

  /// Get column number of anchor item
  FXint getAnchorColumn() const;

  /// Get selection start row; returns -1 if no selection
  FXint getSelStartRow() const;

  /// Get selection start column; returns -1 if no selection
  FXint getSelStartColumn() const;

  /// Get selection end row; returns -1 if no selection
  FXint getSelEndRow() const;

  /// Get selection end column; returns -1 if no selection
  FXint getSelEndColumn() const;

  /// Is item selected?
  FXbool isItemSelected(FXint r,FXint c) const;
  
  /// Is row of cells selected
  FXbool isRowSelected(FXint r) const;

  /// Is column selected
  FXbool isColumnSelected(FXint c) const;

  /// Is anything selected
  FXbool isAnythingSelected() const;

  /// Change font
  void setFont(FXFont* fnt);
  FXFont* getFont() const;

  /// Obtain colors of various parts
  FXColor getTextColor() const;
  FXColor getBaseColor() const;
  FXColor getHiliteColor() const;
  FXColor getShadowColor() const;
  FXColor getBorderColor() const;
  FXColor getSelBackColor() const;
  FXColor getSelTextColor() const;
  FXColor getGridColor() const;
  FXColor getStippleColor() const;
  FXColor getCellBorderColor() const;

  /// Change colors of various parts
  void setTextColor(FXColor clr);
  void setBaseColor(FXColor clr);
  void setHiliteColor(FXColor clr);
  void setShadowColor(FXColor clr);
  void setBorderColor(FXColor clr);
  void setSelBackColor(FXColor clr);
  void setSelTextColor(FXColor clr);
  void setGridColor(FXColor clr);
  void setStippleColor(FXColor clr);
  void setCellBorderColor(FXColor clr);

  /// Change cell background color for even/odd rows/columns
  void setCellColor(FXint ROW_ZERO_OR_ONE,FXint COLUMN_ZERO_OR_ONE,FXColor clr);

  /// Obtain cell background color for even/odd rows/columns
  FXColor getCellColor(FXint ROW_ZERO_OR_ONE,FXint COLUMN_ZERO_OR_ONE) const;

  /// Change cell border width
  void setCellBorderWidth(FXint borderwidth);

  /// Return cell border width
  FXint getCellBorderWidth() const;

  /// Change table style
  FXuint getTableStyle() const;
  void setTableStyle(FXuint style);
  
  /// Change help text
  void setHelpText(const FXString& text);
  FXString getHelpText() const;

  /// Destructor
  virtual ~FXTable();
  };

%clear FXint r;
%clear FXint row;
%clear FXint c;
%clear FXint col;

DECLARE_FXOBJECT_VIRTUALS(FXTable)
DECLARE_FXID_VIRTUALS(FXTable)
DECLARE_FXDRAWABLE_VIRTUALS(FXTable)
DECLARE_FXWINDOW_VIRTUALS(FXTable)
DECLARE_FXSCROLLAREA_VIRTUALS(FXTable)
DECLARE_FXTABLE_VIRTUALS(FXTable)

