// MyCell - version 1.0
// Written by Yanxueming <yanxm2003@hotmail.com>
// Copyright (C) 2006-2006
// All rights reserved.
//
// The code and information is provided "as-is" without
// warranty of any kind, either expressed or implied.
#pragma once
#include <map>
#include <vector>
#include <atlstr.h>
#include "base.h"
using namespace std;
namespace mycell{
class GridBase;
class VaryRowHeightProcy
{
enum eBits
{
B_AllowRowResize=1<<0,
};
protected:
VaryRowHeightProcy():defHeight_(17),bits_(B_AllowRowResize)
{}
public:
void put_DefRowHeight(int hi)
{
defHeight_=hi;
}
int get_DefRowHeight()const
{
return defHeight_;
}
//template<class T>
int get_heights(int rows)const
{
//int const rows=pT->get_rows();
int heights=(rows - int(mapIrregHeights_.size()))*get_DefRowHeight();
for(map<int,int>::const_iterator it=mapIrregHeights_.begin();it!=mapIrregHeights_.end();++it)
{
heights+=it->second;
}
return heights;
}
//[row1,row2)
int get_DiffHeights(int row1,int row2)const
{
if(row1>=row2) return 0;
int heights=(row2-row1)*get_DefRowHeight();
for(map<int,int>::const_iterator it=mapIrregHeights_.begin();it!=mapIrregHeights_.end();++it)
{
if(it->first>=row1 && it->first<row2){
heights-=get_DefRowHeight();
heights+=it->second;
}
}
return heights;
}
void put_RowHeight(int row,int hi)
{
if(hi==defHeight_){
map<int,int>::iterator it=mapIrregHeights_.find(row);
if(it!=mapIrregHeights_.end())
mapIrregHeights_.erase(it);
}else{
mapIrregHeights_[row]=hi;
}
}
int get_RowHeight(int row)const
{
map<int,int>::const_iterator it=mapIrregHeights_.find(row);
return it==mapIrregHeights_.end()?defHeight_:it->second;
}
BOOL get_AllowRowResize()const
{
return bits_&B_AllowRowResize?TRUE:FALSE;
}
void put_AllowRowResize(BOOL bAllow)
{
bAllow?bits_|=B_AllowRowResize:bits_&=~B_AllowRowResize;
}
protected:
void delete_row(int row)
{
map<int,int>::iterator it=mapIrregHeights_.find(row);
if(it!=mapIrregHeights_.end())
mapIrregHeights_.erase(it);
}
void put_rows(int rows)
{
for(map<int,int>::iterator it=mapIrregHeights_.begin();it!=mapIrregHeights_.end();++it)
{
if(it->first>=rows)
it=mapIrregHeights_.erase(it);
}
}
private:
int defHeight_,bits_;
map<int,int> mapIrregHeights_;
};
class FixedRowHeightPolicy
{
int rowHeight_;
public:
FixedRowHeightPolicy():rowHeight_(17)
{}
int get_heights(int rows)const
{
return rows*rowHeight_;
}
//[row1,row2)
int get_DiffHeights(int row1,int row2)const
{
return (row2-row1)*rowHeight_;
}
void put_RowHeight(int row,int hi)
{
}
int get_RowHeight(int row)const
{
return rowHeight_;
}
int get_DefRowHeight()const
{
return rowHeight_;
}
void put_DefRowHeight(int hi)
{
rowHeight_=hi;
}
BOOL get_AllowRowResize()const
{
return FALSE;
}
void put_AllowRowResize(BOOL)
{
}
protected:
void delete_row(int row)
{
}
void put_rows(int rows)
{
}
};
template<class T,class RowHeightProcy=VaryRowHeightProcy>
class RowHeightMgr : public RowHeightProcy
{
protected:
RowHeightMgr(){}
public:
int get_heights()const
{
T const* pT=static_cast<T const*>(this);
return RowHeightProcy::get_heights(pT->get_rows());
}
//[row1,row2)
int get_DiffHeights(int row1,int row2)const
{
return RowHeightProcy::get_DiffHeights(row1,row2);
}
int get_RowHeight(int row)const
{
return RowHeightProcy::get_RowHeight(row);
}
int get_DefRowHeight()const
{
return RowHeightProcy::get_DefRowHeight();
}
void put_DefRowHeight(int hi)
{
RowHeightProcy::put_DefRowHeight(hi);
}
protected:
void put_RowHeight(int row,int hi)
{
RowHeightProcy::put_RowHeight(row,hi);
}
};
class RowHeader;
typedef RowHeightMgr<RowHeader> VaryRowHeightMgr;
typedef RowHeightMgr<RowHeader,FixedRowHeightPolicy> FixedRowHeightMgr;
//#ifdef MYCELL_USE_VARYROWHEADER
typedef VaryRowHeightMgr RowHeightMgrT;
//#else
// typedef FixedRowHeightMgr RowHeightMgrT;
//#endif
struct RowHeaderEvents
{
virtual void OnVisibleRowChanged(int oldTopRow,int oldBottomRow,int newTopRow,int newBottomRow)=0;
};
class RowHeader : public RowHeightMgrT
{
typedef RowHeightMgrT baseClass;
friend class GridBase;
public:
RowHeader():rows_(100),width_(30),topRow_(0),bottomRow_(-1),pEvents_(NULL)
{
}
void SetListener(RowHeaderEvents* p)
{
pEvents_=p;
}
int get_rows()const
{
return rows_;
}
//return validate toprow;
int put_TopRow(int row,LPCRECT lprcContent);
//return new toprow;
int put_BottomRow(int row,LPCRECT lprcContent,BOOL bFullVisible=FALSE);
int get_TopRow()const
{
return topRow_;
}
int calc_TopRow(int height);
int get_BottomRow()const
{
//_ASSERT(-1!=bottomRow_);
return bottomRow_;
}
void put_width(int wi)
{
width_=wi;
}
int get_MinWidth()const
{
return 30;
}
int get_width()const
{
return width_;
}
int get_text(int row,LPTSTR buf)
{
wsprintf(buf,_T("%d"),row+1);
for(int i=0;i!=MAX_CELLTEXT && buf[i];++i)
;
return i;
}
private:
void put_rows(int rows)
{
_ASSERT(rows>=0);
rows_=rows;
//if(bottomRow_>=rows)
// bottomRow_=rows-1;
//if(topRow_>bottomRow_)
// topRow_=bottomRow_;
baseClass::put_rows(rows);
}
void delete_row(int row,LPCRECT lprcContent)
{
baseClass::delete_row(row);
--rows_;
if(row>=topRow_&& row<=bottomRow_){
validate_TopRow(lprcContent);
validate_BottomRow(lprcContent);
}
}
BOOL IsTopRowValidate(LPCRECT lprcContent);
void validate_TopRow(LPCRECT lprcContent);
void validate_BottomRow(LPCRECT lprcContent);
private:
int rows_;
int width_;
int topRow_,bottomRow_;
RowHeaderEvents* pEvents_;
};
//struct ColumnInfo
//{
// CString label;
// CellTypeConstants cellType;
//};
struct ColHeaderEvents
{
virtual void OnVisibleColChanged(int oldLeftCol,int oldRightCol,int newLeftCol,int newRightCol)=0;
};
class ColHeader
{
friend class GridBase;
ColHeader(ColHeader const& rhs);
ColHeader& operator=(ColHeader const& rhs);
public:
explicit ColHeader():cols_(200),defWidth_(80),height_(20),leftCol_(0),rightCol_(-1)
,defColType_(cellDefault),pEvents_(NULL)
{
vecLabel_.resize(cols_);
//vecColInfo_.resize(cols_);
}
void put_DefColType(CellTypeConstants cellType)
{
defColType_=cellType;
}
CellTypeConstants get_DefColType()const
{
return defColType_;
}
void SetListener(ColHeaderEvents* p)
{
pEvents_=p;
}
int get_cols()const
{
return cols_;
}
//return new leftcol
int put_LeftCol(int col,LPCRECT lprcContent);
//return new leftcol
int put_RightCol(int col,LPCRECT lprcContent,BOOL bFullVisible=FALSE);
int get_LeftCol()const
{
return leftCol_;
}
int get_RightCol()const
{
//_ASSERT(-1!=rightCol_);
return rightCol_;
}
void put_DefColWidth(int wi)
{
defWidth_=wi;
}
int get_DefColWidth()const
{
return defWidth_;
}
//[col1,col2)
int get_DiffWidths(int col1,int col2);
int get_widths()const
{
int widths=(cols_-int(mapIrregWidths_.size()))*get_DefColWidth();
for(map<int,int>::const_iterator it=mapIrregWidths_.begin();it!=mapIrregWidths_.end();++it)
widths+=it->second;
return widths;
}
int get_ColWidth(int col)const
{
map<int,int>::const_iterator it=mapIrregWidths_.find(col);
return it==mapIrregWidths_.end()?defWidth_:it->second;
}
void put_height(int hi)
{
height_=hi;
}
int get_height()const
{
return height_;
}
int get_text(int col,LPTSTR buf)
{
_ASSERT(col>=0);
_ASSERT(col<get_cols());
lstrcpy(buf,vecLabel_[col]);
//lstrcpy(buf,vecColInfo_[col].label);
/*
++col;
if(col<27){ //A~Z
buf[0]=(col+0x40);
buf[1]=0;
}else if(col<703){ //AA~ZZ
buf[1]=(col-1)%26+'A';//0x41;
buf[0]=(col-1)/26-1+'A';//0x40;
buf[2]=0;
}
*/
for(int i=0;i!=MAX_CELLTEXT && buf[i];++i)
;
return i;
}
int calc_LeftCol(int width);
void put_ColLabel(int col,LPCTSTR label)
{
_ASSERT(col<cols_);
_ASSERT(col>=0);
vecLabel_[col]=label;
//vecColInfo_[col].label=label;
}
CString const& getref_ColLabel(int col)
{
_ASSERT(col<cols_);
_ASSERT(col>=0);
return vecLabel_[col];
//return vecColInfo_[col].label;
}
CellTypeConstants get_ColType(int col)const
{
map<int,CellTypeConstants>::const_iterator it=mapColType_.find(col);
return it==mapColType_.end()?defColType_:it->second;
}
void put_ColType(int col,CellTypeConstants type)
{
if(defColType_!=type)
mapColType_[col]=type;
}
//CellTypeConstants get_CellType(int col)
//{
// return cellEdit;
//}
private:
void put_cols(int cols)
{
cols_=cols;
vecLabel_.resize(cols_);
for(map<int,int>::iterator it=mapIrregWidths_.begin();it!=mapIrregWidths_.end();++it)
{
if(it->first>=cols){
it=mapIrregWidths_.erase(it);
}
}
//vecColInfo_.resize(cols_);
}
void put_ColWidth(int col,int wi/*,LPCRECT lprcClient*/)
{
if(wi==defWidth_){
map<int,int>::iterator it=mapIrregWidths_.find(col);
if(it!=mapIrregWidths_.end())
mapIrregWidths_.erase(it);
}else{
mapIrregWidths_[col]=wi;
}
//put_LeftCol(get_LeftCol(),lprcClient);
}
void validate_LeftCol(LPCRECT lprcClient);
void validate_RightCol(LPCRECT lprcClient);
private:
int cols_;
int defWidth_,height_;
int leftCol_,rightCol_;
CellTypeConstants defColType_;
map<int,int> mapIrregWidths_;
map<int,CellTypeConstants> mapColType_;
vector<CString> vecLabel_;
ColHeaderEvents* pEvents_;
};
}//namespace mycell