Click here to Skip to main content
15,894,017 members
Articles / Desktop Programming / WTL

A fast and lightweight cell control

Rate me:
Please Sign up or sign in to vote.
4.42/5 (31 votes)
11 Mar 2008CPOL1 min read 91K   4.5K   81  
A fast and lightweight cell control for displaying tabular data. The cell is a custom control derived from ATL::CWindow.
// MyCell - version 1.1
// Written by Yanxueming <yanxm2003@hotmail.com>
// Copyright (C) 2006-2007
// All rights reserved.
//
// The code and information is provided "as-is" without
// warranty of any kind, either expressed or implied.
#include "stdafx.h"
#include "../include/Selections.h"
#include "../include/Worksheet.h"
namespace mycell{
	/*
	void merge_row(vector<RowPair>& vec,int row)
	{
	for(vector<RowPair>::iterator it=vec.begin();it!=vec.end();++it){
	_ASSERT(it->first<=it->second);
	if(row>=it->first && row<=it->second){
	return;
	}else if(row==it->first-1){
	--(it->first);
	return;
	}else if(row==it->second+1){
	++(it->second);
	return;
	}
	}
	vec.push_back(RowPair(row,row));
	}
	*/
	bool Selections::IsOneCell(CCell& cell)const
	{
		if(1==vecSelection_.size()){
			const CCellRange& cr=*vecSelection_.begin();
			if(cr.TopLeft()==cr.RightBottom()){
				cell=cr.TopLeft();
				return true;
			}
		}
		return false;
	}

	void Selections::SetActiveSelection(const CCellRange& newActiveSelection)//int leftCol,int topRow,int rightCol,int bottomRow)
	{
		clear();
		_ASSERT(newActiveSelection.IsNormalize());
		//CCellRange cr(newActiveSelection);
		////cr.set(topRow,leftCol,bottomRow,rightCol);
		//cr.Normalize();
		//vector<CCellRange>::iterator it=find(vecSelection_.begin(),vecSelection_.end(),newActiveSelection);
		//if(it==vecSelection_.end()){
		vecSelection_.push_back(newActiveSelection);
		nActiveSelectionPos_=0;//static_cast<int>(vecSelection_.size())-1;
		//}else
		//	nActiveSelectionPos_=static_cast<int>(it-vecSelection_.begin());
	}
	//bool Selections::IsSelectAll()const
	//{
	//	/*
	//	const CCellRange acr=GetActiveSelection();
	//	const RowHeader& rh=pSheet_->get_RowHeader();
	//	const ColHeader& ch=pSheet_->get_ColHeader();
	//	return HEADER_ROW==acr.TopRow() && HEADER_COL==acr.LeftCol()
	//		&& acr.BottomRow()==rh.get_rows()-1 && acr.RightCol()==ch.get_cols()-1;
	//		*/
	//	return bSelectAll_;
	//}
	void Selections::SelectAll(bool AppendSelection)
	{
		const RowHeader& rh=pSheet_->get_RowHeader();
		const ColHeader& ch=pSheet_->get_ColHeader();
		const CCellRange cr(CCellRange(HEADER_ROW,HEADER_COL,rh.get_rows()-1,ch.get_cols()-1));
		if(AppendSelection)
			AddSelection(cr,true);
		else{
			SetActiveSelection(cr);
		}
		pSheet_->SetActiveCell<false>(rh.IsFreezeRowVisible()?rh.get_FreezeTopRow():rh.get_TopVisScrollRow()
			,ch.IsFreezeColVisible()?ch.get_FreezeLeftCol():ch.get_LeftVisScrollCol());
		bSelectAll_=true;
		if(pSheet_ && pSheet_->IsWindow()){
			pSheet_->RedrawWindow();
		}
	}

	bool Selections::CellInSelections(int row,int col)const
	{
		for(vector<CCellRange>::const_iterator it=vecSelection_.begin();it!=vecSelection_.end();++it)
		{
			if((*it).Inside/*<true>*/(row,col))
				return true;
		}
		return false;
	}
	bool Selections::RowInSelections(int row)const
	{
		for(vector<CCellRange>::const_iterator it=vecSelection_.begin();it!=vecSelection_.end();++it)
		{
			if(it->RowInside(row))
				return true;
		}
		return false;
	}
	bool Selections::ColInSelections(int col)const
	{
		for(vector<CCellRange>::const_iterator it=vecSelection_.begin();it!=vecSelection_.end();++it)
		{
			if(it->ColInside(col))
				return true;
		}
		return false;
	}
	/*
	//void Selections::xor(const Selections& rhs,vector<CCell>& vec)const
	void Selections::Subtract(const Selections& rhs,vector<CCell>& vec,const CCellRange* pClip)const
	{
		CCell cell;
		CCellRange cr;
		for(vector<CCellRange>::const_iterator it=vecSelection_.begin();it!=vecSelection_.end();++it)
		{
			//const CCellRange& cr=*it;
			if(!pClip->GetInterset(*it,cr))
				continue;
			int minr=cr.TopLeft().row,maxr=cr.RightBottom().row,
				minc=cr.TopLeft().col,maxc=cr.RightBottom().col;
			//MinMax<int>(cr.first.row,cr.second.row,minr,maxr);
			//MinMax<int>(cr.first.col,cr.second.col,minc,maxc);
			for(int r=minr;r<=maxr;++r){
				for(int c=minc;c<=maxc;++c){
					if(!rhs.CellInSelections(r,c)){
						cell.set(r,c);
						vec.push_back(cell);
					}
				}
			}
		}
	}
	*/
	void Selections::Xor(const Selections& rhs,CRgnLight& rgn,const CCellRange* pClip)const
	{
		CCellRange cr;
		CRgnLight rgn1,rgn2;
		vector<CCellRange>::const_iterator it;
		for(it=vecSelection_.begin();it!=vecSelection_.end();++it)
		{
			if(!pClip->GetInterset(*it,cr))
				continue;
			rgn1.AddRect(pSheet_->get_RangeRect(cr));
		}
		for(it=rhs.vecSelection_.begin();it!=rhs.vecSelection_.end();++it)
		{
			if(!pClip->GetInterset(*it,cr))
				continue;
			rgn2.AddRect(pSheet_->get_RangeRect(cr));
		}
		rgn.Copy(rgn1);
		rgn.Substract(rgn2);
		rgn2.Substract(rgn1);
		rgn.Combine(rgn2);
	}
	/*
	//��߽������
	void Selections::AdjoinEdge(const Selections& rhs,CRgnLight& rgn,const CCellRange* pClip)const
	{
		Selections ss(pSheet_),ss1(pSheet_);
		vector<CCellRange> vtmp;
		for(vector<CCellRange>::const_iterator it=vecSelection_.begin();it!=vecSelection_.end();++it)
		{
			it->GetEdges(vtmp);
			ss.vecSelection_.insert(ss.vecSelection_.end(),vtmp.begin(),vtmp.end());
			vtmp.clear();
		}
		vector<CCell> vec;
		ss.Clip(*pClip,vec);
		for(vector<CCellRange>::const_iterator it=rhs.vecSelection_.begin();it!=rhs.vecSelection_.end();++it)
		{
			it->GetEdges(vtmp);
			ss1.vecSelection_.insert(ss1.vecSelection_.end(),vtmp.begin(),vtmp.end());
			vtmp.clear();
		}
		int const rows=pSheet_->get_RowHeader().get_rows();
		int const cols=pSheet_->get_ColHeader().get_cols();
		for(vector<CCell>::const_iterator it=vec.begin();it!=vec.end();++it){
			if(it->row<rows-1){
				CCell cell={it->row+1,it->col};
				if(!ss.CellInSelections(cell) && ss1.CellInSelections(cell)){
					rgn.AddRect(pSheet_->raw_GetCellRect(*it));
				}
			}
			if(it->row>0){
				CCell cell={it->row-1,it->col};
				if(!ss.CellInSelections(cell) && ss1.CellInSelections(cell)){
					rgn.AddRect(pSheet_->raw_GetCellRect(*it));
				}
			}
			if(it->col<cols-1){
				CCell cell={it->row,it->col+1};
				if(!ss.CellInSelections(cell) && ss1.CellInSelections(cell)){
					rgn.AddRect(pSheet_->raw_GetCellRect(*it));
				}
			}
			if(it->col>0){
				CCell cell={it->row,it->col-1};
				if(!ss.CellInSelections(cell) && ss1.CellInSelections(cell)){
					rgn.AddRect(pSheet_->raw_GetCellRect(*it));
				}
			}
		}
	}
	//-------------------------------------------------------------------------//
	//��ѡ��cr��ñ�ѡ�񼯻���µ�ѡ�񼯺�retval
	//-------------------------------------------------------------------------//
	void Selections::Clip(const CCellRange& cr,vector<CCell>& vec)const
	{
		CCellRange tmp;
		for(vector<CCellRange>::const_iterator it=vecSelection_.begin();it!=vecSelection_.end();++it)
		{
			if(cr.GetInterset(*it,tmp)){
				tmp.Extract(vec);
			}
		}
	}
	*/
	//void Selections::EnumSelection(vector<CCellRange>& vec,Int2Type<true>)const
	//{
	//	vec=vecSelection_;
	//	for(vector<CCellRange>::iterator it=vec.begin();it!=vec.end();++it)
	//		pSheet_->AdjustSelection(*it);
	//}
	//�����Ǻϲ���Ԫ����������˸÷�������
	//�Ͳ�ε��ã�����ʹ��Ӧ���Ǻϲ���Ԫ������
	ECellBGShrinkState Selections::get_CellBGShrinkState(int row,int col)const
	{
		_ASSERT(row>=0);
		_ASSERT(col>=0);
		if(!CellInSelections(row,col))
			return ECBSS_SHRINK_NONE;
		const RowHeader& rh=pSheet_->get_RowHeader();
		const ColHeader& ch=pSheet_->get_ColHeader();
		int const rows=rh.get_rows();
		int const cols=ch.get_cols();
		_ASSERT(row<rows);
		_ASSERT(col<cols);

		int ecs=0;
		Selections ss(pSheet_);
		for(vector<CCellRange>::const_iterator it=vecSelection_.begin();it!=vecSelection_.end();++it)
		{
			if(it->Inside(row,col))
				ss.AddSelection(*it,false);
		}
		if(0==col || !ss.CellInSelections(row,col-1)){
			ecs|=ECBSS_SHRINK_LEFT;
		}
		if(0==row || !ss.CellInSelections(row-1,col)){
			ecs|=ECBSS_SHRINK_TOP;
		}
		if(cols-1==col || !ss.CellInSelections(row,col+1)){
			ecs|=ECBSS_SHRINK_RIGHT;
		}
		if(rows-1==row || !ss.CellInSelections(row+1,col)){
			ecs|=ECBSS_SHRINK_BOTTOM;
		}
		if(!(ECBSS_SHRINK_LEFT&ecs)&&!(ECBSS_SHRINK_TOP&ecs)
			&&!ss.CellInSelections(row-1,col-1))
		{
			ecs|=ECBSS_SHRINK_LEFTTOP;
		}

		if(!(ECBSS_SHRINK_RIGHT&ecs)&&!(ECBSS_SHRINK_TOP&ecs)
			&&!ss.CellInSelections(row-1,col+1)){
			ecs|=ECBSS_SHRINK_RIGHTTOP;
		}
		//
		if(!(ECBSS_SHRINK_LEFT&ecs)&&!(ECBSS_SHRINK_LEFTBOTTOM&ecs)
			&&!ss.CellInSelections(row+1,col-1)){
			ecs|=ECBSS_SHRINK_LEFTBOTTOM;
		}
		if(!(ECBSS_SHRINK_RIGHT&ecs)&&!(ECBSS_SHRINK_LEFTBOTTOM&ecs)
			&&!ss.CellInSelections(row+1,col+1)){
			ecs|=ECBSS_SHRINK_RIGHTBOTTOM;
		}
		return (ECellBGShrinkState)ecs;
	}
	//[beg,end]
	void Selections::OnColDelete(int beg,int end)
	{
		/*
		int const cols=pSheet_->get_ColHeader().get_cols();
		for(vector<CCellRange>::iterator it=vecSelection_.begin();it!=vecSelection_.end();++it){
			int const leftCol=it->TopRow();
			if(HEADER_COL==leftCol || it->RightCol()>=cols){
				const int rightCol=cols-1;
				if(leftCol>rightCol)
					it->SetLeftCol(rightCol);
				it->SetRightCol(rightCol);
			}
		}
		*/
	}
	//[beg,end]
	void Selections::OnRowDelete(int beg,int end)
	{
		/*
		//if(pSheet_->IsWindow())
		{
			int const rows=pSheet_->get_RowHeader().get_rows();
			for(vector<CCellRange>::iterator it=vecSelection_.begin();it!=vecSelection_.end();++it){
				int const topRow=it->TopRow();
				if(HEADER_ROW==topRow || it->BottomRow()>=rows){
					const int bottomRow=rows-1;
					if(topRow>bottomRow)
						it->SetTopRow(bottomRow);
					it->SetBottomRow(bottomRow);
				}
			}
		}
		*/
	}
	void Selections::OnRowInsertFront(int beg,int nCount)
	{
		/*
		if(pSheet_->IsWindow())
		{
			int const rows=pSheet_->get_RowHeader().get_rows();
			for(vector<CCellRange>::reverse_iterator it=vecSelection_.rbegin();it!=vecSelection_.rend();++it){
				int const topRow=it->TopRow();
				if(HEADER_ROW==topRow || it->BottomRow()>=rows){
					it->SetBottomRow(rows-1);
				}
				if(topRow<=rows && HEADER_ROW!=topRow){
					vecSelection_.pop_back();
				}
			}
		}
		*/
	}
	void Selections::OnMergeCells(int minR,int minC,int maxR,int maxC)
	{
		//const Selections oss=this;
		const CCellRange mcr(minR,minC,maxR,maxC);
		_ASSERT(mcr.IsNormalize());
		for(vector<CCellRange>::iterator it=vecSelection_.begin();it!=vecSelection_.end();++it){
			_ASSERT(it->IsNormalize());
			if(it->IsIntersect(mcr)){
				if(it->LeftCol()>minC)
					it->SetLeftCol(minC);
				if(it->RightCol()<maxC)
					it->SetRightCol(maxC);
				if(it->TopRow()>minR)
					it->SetTopRow(minR);
				if(it->BottomRow()<maxR)
					it->SetBottomRow(maxR);
			}
		}
		//InvalidateContent(pSheet_->GetActiveCell(),oss);
	}
	void Selections::ValidateSelections()
	{
		int const rows=pSheet_->get_RowHeader().get_rows();
		int const cols=pSheet_->get_ColHeader().get_cols();
		for(vector<CCellRange>::reverse_iterator it=vecSelection_.rbegin();it!=vecSelection_.rend();++it){
			int const topRow=it->TopRow();
			int const leftCol=it->LeftCol();
			if(HEADER_ROW==topRow || it->BottomRow()>=rows){
				it->SetBottomRow(rows-1);
			}
			if(topRow>=rows && HEADER_ROW!=topRow){
				vecSelection_.pop_back();
				continue;
			}
			if(HEADER_COL==leftCol || it->RightCol()>=cols){
				it->SetRightCol(cols-1);
			}
			if(leftCol>=cols && HEADER_COL!=leftCol){
				vecSelection_.pop_back();
			}
		}
		CCell acell=pSheet_->GetActiveCell();
		if(acell.row>=rows)
			acell.row=min(0,rows-1);
		if(acell.col>=cols)
			acell.col=min(0,cols-1);
		if(vecSelection_.empty()){
			vecSelection_.push_back(CCellRange(acell));
		}
		if(nActiveSelectionPos_<int(vecSelection_.size())){
			nActiveSelectionPos_=0;
		}
	}
	/*
	ECellState Selections::get_CellState(int row,int col)const
	{
		int ecs=0;
		vector<ECellState> vecCellState;
		for(vector<CCellRange>::const_iterator it=vecSelection_.begin();it!=vecSelection_.end();++it)
		{
			ECellState e=it->get_CellState(row,col);
			if(ECS_FULLINNER&e)
				return ECS_FULLINNER;
			ecs|=e;
			if(it->Inside(row,col))
				vecCellState.push_back(e);
		}
		if(ECS_OUTOF_SELECTION==ecs)
			return (ECellState)ecs;
		//bool bInnerLeft=ECS_INNER_LEFT&ecs;
		//bool bInnerRight=ECS_INNER_RIGHT&ecs;
		//bool bInnerTop=ECS_INNER_TOP&ecs;
		//bool bInnerBottom=ECS_INNER_BOTTOM&ecs;
		for(vector<ECellState>::const_iterator it=vecCellState.begin();it!=vecCellState.end();++it){
			if(!(ECS_INNER_LEFT&(*it))){
				ecs&=~ECS_INNER_LEFT;
				//bInnerLeft=false;
			}
			if(!(ECS_INNER_RIGHT&(*it)))
				ecs&=~ECS_INNER_RIGHT;
				//bInnerRight=false;
			if(!(ECS_INNER_TOP&(*it)))
				ecs&=~ECS_INNER_TOP;
				//bInnerTop=false;
			if(!(ECS_INNER_BOTTOM&(*it)))
				ecs&=~ECS_INNER_BOTTOM;
				//bInnerBottom=false;
		}
		//ECS_OUTOF_SELECTION=1<<0,//��Ԫ����ȫ��ѡ���Ⲣ����ѡ���ı߿�����
		//ECS_FULLINNER=1<<1,//��Ԫ����ȫ��ѡ���ڲ�����ѡ���ı߿�����
		//ECS_INNER_LEFT=1<<2,//��Ԫ����ѡ���ڲ���ѡ����߿�����
		//ECS_INNER_TOP=1<<3,//ѡ���ڿ���
		//ECS_INNER_RIGHT=1<<4,//ѡ���ڿ���
		//ECS_INNER_BOTTOM=1<<5,//ѡ���ڿ���
		//ECS_OUTER_LEFT=1<<6,//ѡ������ѡ����߿�����
		//ECS_OUTER_TOP=1<<7,//ѡ������ѡ���ϱ߿�����
		//ECS_OUTER_RIGHT=1<<8,//ѡ������ѡ���ұ߿�����
		//ECS_OUTER_BOTTOM=1<<9,//ѡ������ѡ���±߿�����

		//if((ECS_INNER_LEFT & ecs) && (ECS_OUTER_LEFT & ecs)){
		//	ecs&=~(ECS_INNER_LEFT|ECS_OUTER_LEFT);
		//}
		return static_cast<ECellState>(ecs);
	}
*/
}//namespace mycell

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
China China
My name is Yanxueming,i live in Chengdu China.Graduated from UESTC in 1999.

Comments and Discussions