/***********************************************************************
 * 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
#define DEFAULT_MARGIN  2


/// Table options
enum {
  TABLE_COL_SIZABLE   = 0x00100000,   /// Columns are resizable
  TABLE_ROW_SIZABLE   = 0x00200000,   /// Rows are resizable
  TABLE_NO_COLSELECT  = 0x00400000,   /// Disallow column selections
  TABLE_NO_ROWSELECT  = 0x00800000    /// 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();
protected:
  enum{
    SELECTED   = 0x00000001,
    FOCUS      = 0x00000002,
    DISABLED   = 0x00000004,
    DRAGGABLE  = 0x00000008,
    BUTTON     = 0x00000010,
    PRESSED    = 0x00000020,
    ICONOWNED  = 0x00000040
    };
public:
  enum{    
    RIGHT      = 0x00002000,      /// Align on right
    LEFT       = 0x00004000,      /// Align on left
    TOP        = 0x00008000,      /// Align on top
    BOTTOM     = 0x00010000,      /// Align on bottom
    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);
      }
    }
  FXString getText() const;
  FXIcon* getIcon() const;
  %extend {
    void setData(VALUE ptr){
      self->setData((void*) ptr);
      }
    VALUE getData() const {
      return self->getData() ? (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 pat);
  FXStipplePattern getStipple() const;
  void setButton(FXbool button);
  FXbool isButton() const;
  void setPressed(FXbool pressed);
  FXbool isPressed() 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->getNumCols()) {
    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->getNumCols()) {
    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->getNumCols()) {
    rb_raise(rb_eIndexError,"table column out of bounds");
  }
}

%typemap(check) FXint leadrows {
  if($1<0 || $1>arg1->getNumRows()-arg1->getTrailingRows()){
    rb_raise(rb_eIndexError,"number out of range");
  }
}

%typemap(check) FXint leadcols {
  if($1<0 || $1>arg1->getNumCols()-arg1->getTrailingCols()){
    rb_raise(rb_eIndexError,"number out of range");
  }
}

%typemap(check) FXint trailrows {
  if($1<0 || $1>arg1->getNumRows()-arg1->getLeadingRows()){
    rb_raise(rb_eIndexError,"number out of range");
  }
}

%typemap(check) FXint trailcols {
  if($1<0 || $1>arg1->getNumCols()-arg1->getLeadingCols()){
    rb_raise(rb_eIndexError,"number out of range");
  }
}

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

/// Table Widget
class FXTable : public FXScrollArea {
protected:
  FXTableItem **cells;                  // Cells
  FXint        *col_x;                  // Vertical grid line positions
  FXint        *row_y;                  // Horizontal grid line positions
  FXFont       *font;                   // Font
  FXint         nrows;                  // Logically allocated rows
  FXint         ncols;                  // Logically allocated columns
  FXint         visiblerows;            // Visible rows
  FXint         visiblecols;            // Visible columns
  FXint         margintop;              // Margin top
  FXint         marginbottom;           // Margin bottom
  FXint         marginleft;             // Margin left
  FXint         marginright;            // Margin right
  FXColor       textColor;              // Normal text color
  FXColor       baseColor;              // Base color
  FXColor       hiliteColor;            // Highlight color
  FXColor       shadowColor;            // Shadow color
  FXColor       borderColor;            // Border color
  FXColor       selbackColor;           // Select background color
  FXColor       seltextColor;           // Select text color
  FXColor       gridColor;              // Grid line color
  FXColor       stippleColor;           // Stipple color
  FXColor       cellBorderColor;        // Cell border color
  FXint         cellBorderWidth;        // Cell border width
  FXColor       cellBackColor[2][2];    // Row/Column even/odd background color
  FXint         defColumnWidth;         // Default column width [if uniform columns]
  FXint         defRowHeight;           // Default row height [if uniform rows]
  FXint         leading_rows;           // Leading fixed rows
  FXint         leading_cols;           // Leading fixed columns
  FXint         scrolling_rows;         // Scrolling rows
  FXint         scrolling_cols;         // Scrolling columns
  FXint         trailing_rows;          // Trailing fixed rows
  FXint         trailing_cols;          // Trailing fixed columns
  FXint         scrollable_left;        // Left side of scrollable part of table
  FXint         scrollable_right;       // Right edge of scrollable part of table
  FXint         scrollable_top;         // Top side of scrollable part of table
  FXint         scrollable_bottom;      // Bottom side of scrollable part of table
  FXint         table_left;             // Left side of table
  FXint         table_right;            // Right edge of right side of table
  FXint         table_top;              // Top side of table
  FXint         table_bottom;           // Bottom side of bottom of table
  FXTableRange  selection;              // Selected cell range
  FXTablePos    current;                // Current position
  FXTablePos    anchor;                 // Anchor position
  FXTablePos    extent;                 // Extent position
  FXint         cellcursor;             // Cursor position in cell
  FXint         cellanchor;             // Anchor position in cell
  FXint         cellscroll;             // Scolled amount in cell
  FXbool        hgrid;                  // Horizontal grid lines shown
  FXbool        vgrid;                  // Vertical grid lines shown
  FXuchar       mode;                   // Mode we're in
  FXint         grabx;                  // Grab point x
  FXint         graby;                  // Grab point y
  FXint         rowcol;                 // Row or column being resized
  FXTimer      *blinker;                // Blink timer
  FXString      help;
public:
  static FXDragType csvType;
  static const FXchar csvTypeName[];
protected:
  FXTable();
  virtual void layout();
  void drawCursor(FXuint state);
  FXRectangle cellRect(FXint r,FXint c) const;
  FXint startRow(FXint row,FXint col) const;
  FXint startCol(FXint row,FXint col) const;
  FXint endRow(FXint row,FXint col) const;
  FXint endCol(FXint row,FXint col) const;
  FXint nearestCol(FXint col,FXint x) const;
  FXint nearestRow(FXint row,FXint y) const;
protected:
  enum {
    MOUSE_NONE,
    MOUSE_SCROLL,
    MOUSE_DRAG,
    MOUSE_SELECT,
    MOUSE_COL_SELECT,
    MOUSE_ROW_SELECT,
    MOUSE_COL_SIZE,
    MOUSE_ROW_SIZE
    };
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 onBlink(FXObject*,FXSelector,void* PTR_IGNORE);
  long onSelectionLost(FXObject*,FXSelector,void* PTR_EVENT);
  long onSelectionGained(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 onCmdSelectAll(FXObject*,FXSelector,void* PTR_IGNORE);
  long onCmdDeselectAll(FXObject*,FXSelector,void* PTR_IGNORE);
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,
    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_BLINK,
    ID_LAST
    };

public:
  
  /// Make new table with nr visible rows and nc visible columns; the table
  /// is initially empty, i.e. contains no cells (nrows=0, ncols=0)
  %extend {
    FXTable(FXComposite* p,FXint nr,FXint nc,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,nr,nc,tgt,sel,opts,x,y,w,h,pl,pr,pt,pb);
      }
    }
  
  /// Change visible rows/columns
  void setVisibleRows(FXint nvrows);
  FXint getVisibleRows() const;
  void setVisibleCols(FXint nvcols);
  FXint getVisibleCols() const;

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

  /// Is vertical grid shown
  FXbool isVertGridShown() const;

  /// Show or hide horizontal grid
  void showHorzGrid(FXbool on=TRUE);

  /// Show or hide vertical grid
  void showVertGrid(FXbool on=TRUE);
  
  %extend {
    /// Resize the table content to nr rows and nc columns
    void setTableSize(FXint nr,FXint nc,FXbool notify=FALSE){
      // Save pointers to the soon-to-be-destroyed items
      FXObjectListOf<FXTableItem> items;
      for(FXint r=0; r<self->getNumRows(); r++){
        for(FXint c=0; c<self->getNumCols(); c++){
	  items.append(self->getItem(r,c));
	  }
	}

      // Do the deed
      self->setTableSize(nr,nc,notify);

      // Now zero-out pointers held by still-alive Ruby objects
      for(FXint i=0;i<items.no();i++){
        FXRbUnregisterRubyObj(items[i]);
        }
      }
  }
  
  /// Get number of rows
  FXint getNumRows() const;

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

  /// Change cell margins
  void setMarginTop(FXint pt);
  FXint getMarginTop() const;
  void setMarginBottom(FXint pb);
  FXint getMarginBottom() const;
  void setMarginLeft(FXint pl);
  FXint getMarginLeft() const;
  void setMarginRight(FXint pr);
  FXint getMarginRight() const;

  /// Change table style
  FXuint getTableStyle() const;
  void setTableStyle(FXuint style);
  
  /// Get/set leading rows
  FXint getLeadingRows() const;

  /// Get/set leading columns
  FXint getLeadingCols() const;

  /// Get/set trailing rows
  FXint getTrailingRows() const;

  /// Get/set trailing columns
  FXint getTrailingCols() const;

  /// Determine row containing y; returns -1 if y outside of table
  FXint rowAtY(FXint y) const;
  
  /// Determine column containing x; returns -1 if x outside of table
  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){
      if(item!=0 && item->isMemberOf(FXMETACLASS(FXRbTableItem))){
        dynamic_cast<FXRbTableItem*>(item)->owned=TRUE;
        }
      self->setItem(row,col,item);
      }
  }

  /// Scroll to make cell at r,c fully visible
  void makePositionVisible(FXint r,FXint c);
  
  /// Change column width
  void setColumnWidth(FXint col,FXint cwidth);
  FXint getColumnWidth(FXint col) const;

  /// Change row height
  void setRowHeight(FXint row,FXint rheight);
  FXint getRowHeight(FXint row) const;

  %extend {
    /// Change X coordinate of column c
    void setColumnX(FXint colEdge,FXint x){
      if(colEdge<0 || colEdge>self->getNumCols()){
        rb_raise(rb_eIndexError,"table column out of bounds");
        }
      self->setColumnX(colEdge,x);
      }
    FXint getColumnX(FXint colEdge) const {
      if(colEdge<0 || colEdge>self->getNumCols()){
        rb_raise(rb_eIndexError,"table column out of bounds");
        }
      return self->getColumnX(colEdge);
      }
  
    /// Change Y coordinate of row r
    void setRowY(FXint rowEdge,FXint y){
      if(rowEdge<0 || rowEdge>self->getNumRows()){
        rb_raise(rb_eIndexError,"table row out of bounds");
        }
      self->setRowY(rowEdge,y);
      }
    FXint getRowY(FXint rowEdge) const {
      if(rowEdge<0 || rowEdge>self->getNumRows()){
        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;

  %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;
      }
  }
  
  /// Is cell selected, current, visible, enabled
  FXbool isItemSelected(FXint r,FXint c) const;
  FXbool isItemCurrent(FXint r,FXint c) const;
  FXbool isItemVisible(FXint r,FXint c) const;
  FXbool isItemEnabled(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){
      if(sr<0 || sc<0 || er>self->getNumRows() || ec>self->getNumCols()){
	rb_raise(rb_eIndexError,"index out of bounds");
        }
      else{
	self->updateRange(sr,er,sc,ec);
	}
      }
  }

  /// Repaint cell at r,c
  void updateItem(FXint r,FXint c);
  
  /// Enable, disable, select, deselect, toggle cell
  FXbool enableItem(FXint r,FXint c);
  FXbool disableItem(FXint r,FXint c);
  FXbool selectItem(FXint r,FXint c,FXbool notify=FALSE);
  FXbool deselectItem(FXint r,FXint c,FXbool notify=FALSE);
  FXbool toggleItem(FXint r,FXint c,FXbool notify=FALSE);
  
  /// Change current cell
  void setCurrentItem(FXint r,FXint c,FXbool notify=FALSE);
  FXint getCurrentRow() const;
  FXint getCurrentColumn() const;

  /// Change anchored cell
  void setAnchorItem(FXint r,FXint c);
  FXint getAnchorRow() const;
  FXint getAnchorColumn() const;

  /// Select range
  FXbool selectRange(FXint sr,FXint er,FXint sc,FXint ec,FXbool notify=FALSE);

  /// Extend selection
  FXbool extendSelection(FXint r,FXint c,FXbool notify=FALSE);

  /// Kill selection
  FXbool killSelection(FXbool notify=FALSE);

  /// 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 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;
%clear FXint leadrows;
%clear FXint leadcols;
%clear FXint trailrows;
%clear FXint trailcols;

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

