/////////////////////////////////////////////////////////////////////////////
// Name:        wxGenericListCtrl
// Purpose:     
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     2000/07/27
// RCS-ID:      $Id: glist.h,v 1.2 2001/04/20 11:27:29 georgetasker Exp $
// Copyright:   (c) 2000 PM-Soft
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

#ifndef __GENLIST_G__
#define __GENLIST_G__

#include "wx/scrolwin.h"
#include "wx/dynarray.h"
#include "wx/imaglist.h"
#include "wx/dcmemory.h"

// TBD:: should be abstract class

class wxListModel;

typedef int (*ListModelCompareT)(wxListModel* pList, int row1, int row2, int col);

class wxListModel
{
public:
  wxListModel();
  virtual ~wxListModel();

  virtual void PrepareRow(int row);
  virtual const wxString GetValue(int row, int col);
  virtual int GetRowCount();
  virtual int GetFinalRowCount(); // TBD:: comments

  virtual void SetRowCount(int count);

  virtual void Sort(size_t byColumn, bool acending);
  virtual void Sort(size_t byColumn, ListModelCompareT compFn);

  virtual void SwapRows(int row1, int row2);

  virtual void SetAscendingSortFunctino(ListModelCompareT ascFn);
  virtual void SetDescendingSortFunction(ListModelCompareT descFn);

  // only called when instance of wxImageList is set to wxGenericListCtrl
  virtual int GetImageForRow(int row);

protected:
  int mRowCount; // just for testing purposes
  ListModelCompareT mAscSortFn;
  ListModelCompareT mDescSortFn;
};

WX_DEFINE_ARRAY(wxString*, wxStrArrayT);

class wxSimpleListModel : public wxListModel
{
public:
  wxSimpleListModel();
  ~wxSimpleListModel();

  virtual void SetColumnCount(int cols);
  virtual int GetColumnCount();

  void AppendRow();
  void AppendRows(int nRows);
  void SetValue(const char* value, int row, int col);

  /*** overiden methods of wxListModel ***/

  virtual const wxString GetValue(int row, int col);

  virtual void Sort(size_t byColumn, bool acending);
  virtual void Sort(size_t byColumn, ListModelCompareT sortFn);

  virtual void SwapRows(int row1, int row2);

protected:
  wxStrArrayT mValues;
  int     mColCount;
};

class wxListCellPainter : public wxObject
{
public:
  virtual void OnDrawCellBackground(wxDC& dc, wxRect& rect, int row, int col ) = 0;
  virtual void OnDrawCellContent(wxDC& dc, wxRect& rect, int row, int col ) = 0;
  virtual void OnCellSelected(int row, int col) = 0;
  virtual void OnCellDeselected(int row, int col) = 0;
};

class wxGenericListCtrl : public wxScrolledWindow
{
public:
  wxGenericListCtrl();

  wxGenericListCtrl( wxWindow* parent, wxWindowID id, 
					 const wxPoint& pos = wxDefaultPosition, 
					 const wxSize& size = wxDefaultSize, 
					 long style = 0, const wxString& name = "gListCtrl" );

  void SetDefaults();

  ~wxGenericListCtrl();

  virtual void AddColumn(const wxString& name, int width = 70);
  virtual void SetModel(wxListModel* pModel);
  virtual wxListModel* GetModel();
  
  /*** seleciton management ***/

  // resets all previously selected row, and sets single selection
  // (updates screen content immediately)
  virtual void SelectRow(int row); 

  // returns focused row within multiple or single selection
  virtual int GetFocusedRow();
  virtual wxArrayInt& GetSelection();

  // NOTE:: fails, if given row is not within current selection
  // NOTE2:: all the below methods do not update screen content immediately 

  virtual void SetFocusedRow(int row);
  virtual void SetSelection(wxArrayInt& rows);

  // managment multiple selection incramentally
  virtual void SelectRow(int row, bool select);
  virtual bool IsSelected(int row);

  virtual int GetHorzintalScrollStep();
  virtual void SetHorizontalScrollStep(int pixels);

  /****************************/

  virtual void SetReduceFlicker(bool reduce);
  virtual void SetShowSortMarker(bool show);
  virtual void SetCellPainter(wxListCellPainter* pPainter);

  // bitmap is drawn on the first column of each row, 
  // left to the cell's text
  virtual void SetRowBitmap(const wxBitmap& bmp);

  // note given instance is not destroy by this listctrl
  virtual void SetImageList(wxImageList* pList);

  virtual void RemoveAllColumns();

  virtual void LayoutHeadingsByWidths();
  virtual void StretchHeadingsToWidth();

  virtual void SetColumnWidth(int col, int width, bool refreshNow = FALSE);
  virtual void SetColumnName(int col, const wxString& name, bool refreshNow = FALSE);
  virtual void SetColumnAlignment(int col, int align = wxLEFT);

  // notification
  virtual void OnFontChanged();

  // event handlers 

  void OnLeftDown(wxMouseEvent& event);
  void OnMotion(wxMouseEvent& event);
  void OnLeftUp(wxMouseEvent& event);

  void PrepareDC(wxDC& dc);

  void OnPaint(wxPaintEvent& event);
  void OnEraseBackground(wxEraseEvent& event);
  void OnKeyDown(wxKeyEvent& event);
  void OnSize(wxSizeEvent& event);

  void GetPageInfo(int& firstRow, int& rowsVisible);
  int GetFirstVisibleRow();
  int GetVisibleRowsCount();

  void UpdateScrollBars(int scrollX = -1, int scrollY = -1);
  int GetWidth();
  int GetHeight();
  int GetRowWidth();
  int GetHeadingRowHeight();
  int GetRowAt(int yPos);
  bool IsVisible(int row);
  int GetColumnCount();
  wxString GetColumnName(int col);
  int GetColumnWidth(int col);
  wxStringList& GetColumnNames();

  // returns -1, if column with given name does not exist
  int GetColumnIndex(const wxString& columnName);

  wxFont GetHeadingFont();
  wxFont GetContentFont();

  wxColour& GetSelectionColour();

  DECLARE_CLASS(wxGenericListCtrl)
  DECLARE_EVENT_TABLE()

protected:
  virtual void DrawHeadingCol(wxDC& dc, int x, int width, bool isPressed);
  virtual void DrawHeadings(wxDC& toDc);
  virtual void DrawPageContent(wxDC& dc);
  virtual void DrawRows(wxDC& toDc, int from, int till);
  virtual void FillEmptyAreas(wxDC& toDc);
  virtual void UpdateHeadings();
  virtual bool HitTestHeadings(int x, int &heading, int& part);
  virtual void RelayoutHeadings(bool byWidths);
  virtual bool SyncPageWithSelection();
  virtual bool IsVisibleColumn(int col);

  virtual int ToViewX(wxMouseEvent& event);

  virtual wxDC& GetBufferDc(wxDC& toDc);
  virtual void FlushBufferDc(wxDC& toDc);

  virtual void SetSortOptionForColumn(int col, bool acending);
  virtual int GetLastSortedColumn();
  virtual bool IsSortedAscending();

protected:
  // Variablen declared in order as used in constuctor, avoiding warnings in gcc
  int                mRowHeight;
  int                mLeadingHeight;
  int                mHeadingHeight;
  wxListModel       *mpModel;
  int                mRowsPerUnit;
  int                mFocusedRow;
  bool               mHeadingDragStarted;
  int                mHeadingPart;
  int                mDraggedHeading;
  int                mPressedHeading;
  int                mRowWidth;
  int                mTextLeftMargin;
  int                mTextRightMargin;
  wxBitmap          *mpBufBmp;
  wxMemoryDC        *mpBufDc;
  bool               mUserBackBuffer;
  wxListCellPainter *mpCellPainter;
  wxColour           mSelColour;
  bool               mShowSortMarker;
  int                mLastSortedCol;
  wxImageList       *mpImageList;
  int                mHorizScrollStep; // default: 50

  wxArrayInt         mColPositions;
  wxArrayInt         mColWidths;
  wxArrayInt         mColSortOptions;
  wxArrayInt         mColAlignOptions;
  wxStringList       mColNames;
  wxArrayInt         mSelection;

  wxFont             mOldFont;
  wxBitmap           mRowBitmap;

  enum HEADING_PARTS_ENUM
  {
    HITS_LEFT_CORNER,
    HITS_RIGHT_CORNER,
    HITS_INTERIOR
  };
};
#endif // __GENLIST_G__
