/*
 * ===========================
 * VDK Visual Development Kit
 * Version 0.5
 * November 1998
 * ===========================
 *
 * Copyright (C) 1998, Mario Motta
 * Developed by Mario Motta <mmotta@guest.net>
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA
 * 02111-130
 */

#ifndef VDKCLIST_H
#define VDKCLIST_H
#include <vdk/vdkcustom.h>
//#include <vector>
//#include <string>
/*
 */
class VDKCustomList;

typedef VDKReadWriteValueProp<VDKCustomList,VDKPoint>
                               CustomListSelProperty;

class SelectionProp: public CustomListSelProperty
{
 public:
  SelectionProp(
		char* name,
	       	VDKCustomList* object,
	       	VDKPoint defValue,
	       	void (VDKCustomList::*write)(VDKPoint),
	       	VDKPoint (VDKCustomList::*read)(void) =
		(VDKPoint (VDKCustomList::*)(void)) NULL
	       	):CustomListSelProperty(name,object,defValue,write,read)
    { }

  int Row()const { return Value().X();}
  int Col()const { return Value().Y();}

};

/*!
  \class VDKCustomList
  \brief This class wraps gtkclist widget.

  \par Signals
  \arg \b select_row signal, emitted on selecting a list cell (or double
  clicking on extended selection mode). Selected property contains
  selected cell coordinates. Selected is set to VDKPoint(-1,-1) if no
  cell is selected.
  \arg \b unselect_row_signal, emitted on unselecting a cell. Unselected property
  contains unselected cell coordinates.
  \arg \b click_column_signal, emitted on clicking over a column titile, 
  ColumnClicked() returns wich column was clicked.
  
  \par Tip
  Use Selected property property like this:
  \code
  VDKPoint p = list->Selected;
  int row = p.x;
  int col = p.y;
  // or simpler
  int row = list->Selected.Row();
  int col = list->Selected.Col();
  \endcode

  \par Programming hints
  Data contained into a VDKCustomList are organized as a list of tuples,
  a VDKTuple is a derived clas of an VDKArray<VDKString> that add 
  equality and less-than operators (See vdkclist.h for further informations).
  You can access to data using [] operator on Tuples property like this:
  \code
  VDKTuple tuple = list->Tuples[j]; // access to j-th tuple
  VDKString s = list->Tuples[j][i]; // access to j-th,i-th string
  \endcode
  Recall that Tuples is a read-only property, directly modifying a tuple 
  does not reflect into the list widget, use VDKCustomList::UpdateRow()
  method at this end.

  \par Examples
  Into ./testvdk/testvdk.cc and .h
*/
class VDKCustomList: public VDKCustom
{

 protected:
  VDKIntArray WideSelection;
  VDKPoint selection, unselection; // selected row,column
  // extended selection
  int pointer;
  // wide selection
  int start,end;
  void _update_pix(int row,const char* s, char** pixdata = NULL, int col = 0);
  void _update_size(int row,int *W, int *H);
  void SetStyle(int row);
  void ConnectSignals();
  // handle title clicks
  static void ColumnClick(GtkWidget* w,
			  gint column,
			  gpointer s);

  // handle selection in modes != EXTENDED
  static int RowSelection(GtkWidget *wid,
			   gint row,
			     gint column,
			   GdkEvent *event,
			   gpointer data);
  static int RowUnselection(GtkWidget *wid,
			     gint row,
			     gint column,
			     GdkEventButton *event,
			     gpointer data);


 public:
    // properties
  /*!
    Use this to know wich cell is selected or Selected.Row() or
    Selected.Col() <read-only>
  */
  SelectionProp Selected;
  /*!
    Use this to know wich cell is unselected or Unselected.Row() or
    Unselected.Col() <read-only>
  */
  SelectionProp Unselected;
  /*!
    A tuple is a VDKArray<VDKString>. use this property to access data
    on row/cell basis like this:
    \code
    Tuple  tuple = list->Tuples[0];
    char * p = (char*) tuple[0];
    // or more simply
    char *p = (char*) list->Tuples[0][0];
    \endcode
   */
    TupleList Tuples;

 public:
    /*!
    Constructor.
    \param columns columns number
    \param titles array of titles strings
    \param mode selection mode
     */
  VDKCustomList(VDKForm* owner,
		int columns = 1,
		char **titles = NULL,
		GtkSelectionMode mode = GTK_SELECTION_SINGLE);
  /*!
    Destructor
  */
  virtual ~VDKCustomList();
  //void AddRow(vector<string> v, char** pixdata = NULL, int col = 0);
  /*!
    Add a row to list.
    \param texts strings array to fill row cells
    \param pixdata a cell can have a pixmap
    \param wich column has the pixmap (if any)
   */
  void AddRow(char **texts, char** pixdata = NULL, int col = 0);
  /*!
    Updates a row
    \param row wich row should be updated
    \param pixdata a cell can have a pixmap
    \param wich column has the pixmap (if any)
  */
  void UpdateRow(int row, char** s,
	      char** pixdata = NULL, int col = 0);
  /*!
    Same as above
  */
  void UpdateRow(int row, Tuple& t,
	      char** pixdata = NULL, int col = 0);
  /*!
    Updates a cell
    \param row cell coordinates
    \param col
    \param pixdata a cell can have a pixmap
    \param wich column has the pixmap (if any)
  */
  void UpdateCell(int row, int col,
		  const char* s, char** pixdata = NULL);
  /*!
    Removes a row
    \param row, whic row should be removed
  */
  void RemoveRow(int row);
  /*!
    Returns selected cell coordinates
  */
  VDKPoint Selection() { return selection; }
  /*!
    Returns unselected cell coordinates
  */
  VDKPoint Unselection() { return unselection; }
  /*!
    Selects a row
    \param row, cell coordinate
    \param col
  */
  void SelectRow(int row, int col);
  /*!
    Selects a row
    \param p, cell coordinates
  */
  void SelectRow(VDKPoint p) { SelectRow(p.X(),p.Y()); }
  /*!
    Unselects a row
    \param row, cell coordinate
    \param col
  */
  void UnselectRow(int row, int col);
  /*!
    Selects a row
    \param p, cell coordinates
  */
  void UnselectRow(VDKPoint p) { UnselectRow(p.X(),p.Y()); }

  virtual void Clear();
  /*!
    Returns an array filled with all selected row number. Valid only in
    multiple or extended selection mode, in other cases array will have
    size == 0
  */
  VDKIntArray& Selections();
#ifdef USE_SIGCPLUSPLUS
 public:
  /*!
    Extended LS signal system:
    Received when a cell is selected
    \param int row
    \param int column
  */
  VDKSignal2<void, int, int> OnRowSelect; 
  /*!
    Extended LS signal system:
    Received when a cell is unselected
    \param int row
    \param int column
  */
  VDKSignal2<void, int, int> OnRowUnselect;
  /*!
    Extended LS signal system:
    Received when a row is moved
    \param int from
    \param int to
  */
  VDKSignal2<void, int, int> OnRowMove;
       
//  VDKSignal2<void, int, const char**> OnRowInsert; 
//  VDKSignal1<void, int> OnRowRemove;
 protected:
  static void make_gtksigc_connection(VDKCustomList*);
 private:
  static void _handle_row_move(GtkWidget* wid, int, int,
			       gpointer obj);
//  static void _handle_row_insert(GtkWidget* wid, int, char**,
//				 gpointer obj);
//  static void _handle_row_remove(GtkWidget* wid, int row,
//				 gpointer obj);
#endif /* USE_SIGCPLUSPLUS */
};
#endif

