/********************************************************************************
*                                                                               *
*                            T a b l e   W i d g e t                            *
*                                                                               *
*********************************************************************************
* Copyright (C) 1999 by Jeroen van der Zijp.   All Rights Reserved.             *
*********************************************************************************
* This library is free software; you can redistribute it and/or                 *
* modify it under the terms of the GNU Library General Public                   *
* License as published by the Free Software Foundation; either                  *
* version 2 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             *
* Library General Public License for more details.                              *
*                                                                               *
* You should have received a copy of the GNU Library General Public             *
* License along with this library; if not, write to the Free                    *
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
*********************************************************************************
* $Id: FXTable.h,v 1.44 2001/03/08 18:23:18 jeroen Exp $                        *
********************************************************************************/
#ifndef FXTABLE_H
#define FXTABLE_H


//////////////////////////////  UNDER DEVELOPMENT  //////////////////////////////


// Default cell margin
#define DEFAULT_MARGIN  2



// Table options
enum {
  TABLE_HOR_GRIDLINES   = 0x00100000,   /// Horizontal grid lines
  TABLE_VER_GRIDLINES   = 0x00200000    /// Vertical grid lines
  };


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


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


/// Item in table
class FXAPI FXTableItem : public FXObject {
  FXDECLARE(FXTableItem)
  friend class FXTable;
protected:
  FXString    label;
  FXIcon*     icon;
  void       *data;
  FXuint      state;
protected:
  FXTableItem():icon(NULL),data(NULL),state(0){}
  virtual void draw(const FXTable* table,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const;
  void drawFocus(const FXTable* table,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const;
  void drawRaised(const FXTable* table,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const;
  void drawSunken(const FXTable* table,FXDC& dc,FXint x,FXint y,FXint w,FXint h) const;
//  void drawTextFragment(FXDCWindow& dc,FXString& string,FXint x,FXint y,FXuint fm,FXuint to);
//   void drawTextRange(FXString& string,FXint x,FXint y,FXint w,FXint h,FXuint mode,FXuint fm,FXuint to,FXuint si,FXuint ei,FXint scroll);
protected:
  enum{
    SELECTED  = 1,
    MARKED    = 2,
    FOCUS     = 4,
    DISABLED  = 8,
    DRAGGABLE = 16,
    RIGHT     = 32,
    LEFT      = 64,
    TOP       = 128,
    BOTTOM    = 256,
    BUTTON    = 512,
    PRESSED   = 1024
    };
public:
  FXTableItem(const FXString& text,FXIcon* ic=NULL,void* ptr=NULL):label(text),icon(ic),data(ptr),state(FXTableItem::RIGHT){}
  virtual void setText(const FXString& txt){ label=txt; }
  FXString getText() const { return label; }
  virtual void setIcon(FXIcon* icn){ icon=icn; }
  FXIcon* getIcon() const { return icon; }
  void setData(void* ptr){ data=ptr; }
  void* getData() const { return data; }
  virtual void setFocus(FXbool focus);
  FXbool hasFocus() const { return (state&FOCUS)!=0; }
  virtual void setSelected(FXbool selected);
  FXbool isSelected() const { return (state&SELECTED)!=0; }
  virtual void setEnabled(FXbool enabled);
  FXbool isEnabled() const { return (state&DISABLED)==0; }
  virtual void setDraggable(FXbool draggable);
  FXbool isDraggable() const { return (state&DRAGGABLE)!=0; }
  virtual void setMarked(FXbool marked);
  FXbool isMarked() const { return (state&MARKED)!=0; }
  virtual void setJustify(FXuint justify);
  FXuint getJustify() const { return state&(RIGHT|LEFT|TOP|BOTTOM); }
  virtual FXint getWidth(const FXTable* table) const;
  virtual FXint getHeight(const FXTable* table) const;
  virtual void create();
  virtual void detach();
  virtual void destroy();
  virtual void save(FXStream& store) const;
  virtual void load(FXStream& store);
  virtual ~FXTableItem(){}
  };



/// Table Widget
class FXAPI FXTable : public FXScrollArea {
  FXDECLARE(FXTable)
protected:
  FXTableItem **cells;                  // Cells
  FXint        *col_x;                  // Column starts [if non-uniform]
  FXint        *row_y;                  // Row starts [if non-uniform]
  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       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         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
  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
  FXuchar       mode;                   // Mode we're in
  FXint         grabx;                  // Grab point x
  FXint         graby;                  // Grab point y
  FXTimer      *blinker;                // Blink timer
  FXString      help;
protected:
  FXTable();
  virtual void layout();
  FXint yOfRow(FXint r) const;
  FXint xOfCol(FXint c) const;
  void drawCursor(FXuint state);
  FXbool restore(FXint rlo,FXint rhi,FXint clo,FXint chi);
  static FXint bsearch(FXint *array,FXint l,FXint h,FXint value);
  FXbool mark(FXint rlo,FXint rhi,FXint clo,FXint chi,FXuint sel);
  void drawTableRange(FXDC& dc,FXint xlo,FXint xhi,FXint ylo,FXint yhi,FXint xoff,FXint yoff,FXint rlo,FXint rhi,FXint clo,FXint chi);
  virtual FXTableItem* createItem(const FXString& text,FXIcon* icon,void* ptr);
private:
  FXTable(const FXTable&);
  FXTable& operator=(const FXTable&);
public:
  long onPaint(FXObject*,FXSelector,void*);
  long onKeyPress(FXObject*,FXSelector,void*);
  long onKeyRelease(FXObject*,FXSelector,void*);
  long onLeftBtnPress(FXObject*,FXSelector,void*);
  long onLeftBtnRelease(FXObject*,FXSelector,void*);
  long onRightBtnPress(FXObject*,FXSelector,void*);
  long onRightBtnRelease(FXObject*,FXSelector,void*);
  long onUngrabbed(FXObject*,FXSelector,void*);
  long onActivate(FXObject*,FXSelector,void*);
  long onDeactivate(FXObject*,FXSelector,void*);
  long onSelected(FXObject*,FXSelector,void*);
  long onDeselected(FXObject*,FXSelector,void*);
  long onInserted(FXObject*,FXSelector,void*);
  long onDeleted(FXObject*,FXSelector,void*);
  long onFocusIn(FXObject*,FXSelector,void*);
  long onFocusOut(FXObject*,FXSelector,void*);
  long onBlink(FXObject*,FXSelector,void*);
  long onSelectionLost(FXObject*,FXSelector,void*);
  long onSelectionGained(FXObject*,FXSelector,void*);
  long onAutoScroll(FXObject*,FXSelector,void*);
  long onMotion(FXObject*,FXSelector,void*);
  long onChanged(FXObject*,FXSelector,void*);
  long onCommand(FXObject*,FXSelector,void*);
  long onClicked(FXObject*,FXSelector,void*);
  long onDoubleClicked(FXObject*,FXSelector,void*);
  long onTripleClicked(FXObject*,FXSelector,void*);

  // Visual characteristics
  long onCmdHorzGrid(FXObject*,FXSelector,void*);
  long onUpdHorzGrid(FXObject*,FXSelector,void*);
  long onCmdVertGrid(FXObject*,FXSelector,void*);
  long onUpdVertGrid(FXObject*,FXSelector,void*);

  // Row/Column manipulations
  long onCmdDeleteColumn(FXObject*,FXSelector,void*);
  long onUpdDeleteColumn(FXObject*,FXSelector,void*);
  long onCmdDeleteRow(FXObject*,FXSelector,void*);
  long onUpdDeleteRow(FXObject*,FXSelector,void*);
  long onCmdInsertColumn(FXObject*,FXSelector,void*);
  long onCmdInsertRow(FXObject*,FXSelector,void*);

  // Movement
  long onCmdMoveRight(FXObject*,FXSelector,void*);
  long onCmdMoveLeft(FXObject*,FXSelector,void*);
  long onCmdMoveUp(FXObject*,FXSelector,void*);
  long onCmdMoveDown(FXObject*,FXSelector,void*);

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

  // Changing Selection
  long onCmdSelectCell(FXObject*,FXSelector,void*);
  long onCmdSelectRow(FXObject*,FXSelector,void*);
  long onCmdSelectColumn(FXObject*,FXSelector,void*);
  long onCmdSelectAll(FXObject*,FXSelector,void*);
  long onCmdDeselectAll(FXObject*,FXSelector,void*);
public:

  // Messages
  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_MARK,
    ID_EXTEND,
    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)
  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);
  virtual void create();
  virtual void detach();
  virtual void recalc();
  virtual FXbool canFocus() const;

  /// Change visible rows/columns
  void setVisibleRows(FXint nvrows);
  FXint getVisibleRows() const { return visiblerows; }
  void setVisibleCols(FXint nvcols);
  FXint getVisibleCols() const { return visiblecols; }

  /// Report default size, which is determined based on the
  /// visible rows/columns and the default width/height
  virtual FXint getDefaultWidth();
  virtual FXint getDefaultHeight();

  /// Compute content size
  virtual FXint getContentWidth();
  virtual FXint getContentHeight();

  /// Scroll contents
  virtual void moveContents(FXint x,FXint y);

  /// Resize the table content to nr rows and nc columns
  void setTableSize(FXint nr,FXint nc);

  /// Get number of rows
  FXint getNumRows() const { return nrows; }

  /// Get number of columns
  FXint getNumCols() const { return ncols; }

  /// Change cell margins
  void setMarginTop(FXint pt);
  FXint getMarginTop() const { return margintop; }
  void setMarginBottom(FXint pb);
  FXint getMarginBottom() const { return marginbottom; }
  void setMarginLeft(FXint pl);
  FXint getMarginLeft() const { return marginleft; }
  void setMarginRight(FXint pr);
  FXint getMarginRight() const { return marginright; }

  /// Change table style
  FXuint getTableStyle() const;
  void setTableStyle(FXuint style);

  /// Get/set leading rows
  virtual void setLeadingRows(FXint leadrows);
  FXint getLeadingRows() const { return leading_rows; }

  /// Get/set leading columns
  virtual void setLeadingCols(FXint leadcols);
  FXint getLeadingCols() const { return leading_cols; }

  /// Get/set trailing rows
  virtual void setTrailingRows(FXint trailrows);
  FXint getTrailingRows() const { return trailing_rows; }

  /// Get/set trailing columns
  virtual void setTrailingCols(FXint trailcols);
  FXint getTrailingCols() const { return trailing_cols; }

  /// 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;

  /// Insert new row
  virtual void insertRows(FXint row,FXint nr=1);

  /// Insert new column
  virtual void insertColumns(FXint col,FXint nc=1);

  /// Delete row
  virtual void deleteRows(FXint row,FXint nr=1);

  /// Delete column
  virtual void deleteColumns(FXint col,FXint nc=1);

  /// 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;

  /// Change default column width
  void setDefColumnWidth(FXint cwidth);
  FXint getDefColumnWidth() const { return defColumnWidth; }

  /// Change default row height
  void setDefRowHeight(FXint rheight);
  FXint getDefRowHeight() const { return defRowHeight; }

  /// Modify cell text
  void setItemText(FXint r,FXint c,const FXString& text);
  FXString getItemText(FXint r,FXint c) const;

  /// Modify cell icon
  void setItemIcon(FXint r,FXint c,FXIcon* icon);
  FXIcon* getItemIcon(FXint r,FXint c) const;

  /// Modify cell user-data
  void setItemData(FXint r,FXint c,void* ptr);
  void* getItemData(FXint r,FXint c) const;

  /// 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;

  /// Repaint cell
  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 deselectItem(FXint r,FXint c);
  FXbool toggleItem(FXint r,FXint c);

  /// Change current cell
  void setCurrentItem(FXint r,FXint c);
  FXint getCurrentRow() const { return current.row; }
  FXint getCurrentColumn() const { return current.col; }

  /// Change anchored cell
  void setAnchorItem(FXint r,FXint c);
  FXint getAnchorRow() const { return anchor.row; }
  FXint getAnchorColumn() const { return anchor.col; }

  /// Extend/kill selection
  FXbool extendSelection(FXint r,FXint c);
  FXbool killSelection();

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

  /// Change colors of various aspects
  void setTextColor(FXColor clr);
  FXColor getTextColor() const { return textColor; }
  void setBaseColor(FXColor clr);
  FXColor getBaseColor() const { return baseColor; }
  void setHiliteColor(FXColor clr);
  FXColor getHiliteColor() const { return hiliteColor; }
  void setShadowColor(FXColor clr);
  FXColor getShadowColor() const { return shadowColor; }
  void setBorderColor(FXColor clr);
  FXColor getBorderColor() const { return borderColor; }
  void setSelBackColor(FXColor clr);
  FXColor getSelBackColor() const { return selbackColor; }
  void setSelTextColor(FXColor clr);
  FXColor getSelTextColor() const { return seltextColor; }
  void setGridColor(FXColor clr);
  FXColor getGridColor() const { return gridColor; }

  /// Change cell background color for even/odd rows/columns
  void setCellColor(FXint r,FXint c,FXColor clr);
  FXColor getCellColor(FXint r,FXint c) const;

  /// Change help text
  void setHelpText(const FXString& text);
  FXString getHelpText() const { return help; }

  /// Serialize
  virtual void save(FXStream& store) const;
  virtual void load(FXStream& store);

  virtual ~FXTable();
  };



#endif
