// Item.cpp: implementation of the CItem class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Graph.h"
#include "Item.h"
#include "GraphViewFX.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
extern "C"
{
void DrawGradientFill(CDC* pDC, CRect* prc, int nSegs,
COLORREF crStart, COLORREF crEnd, BOOL bSemiFormat, CRect* prcFull);
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#include <time.h>
CItem::CItem(CWnd* pWnd)
{
m_bSelect = false;
m_nOrdinal = -1;
m_pWnd = dynamic_cast<CGraphViewFX*>(pWnd);
m_strName = "Default Item";
// Usually this is be zero
// m_nPercentage = 0;
m_nHiWaterMark = 0;
}
CItem::~CItem()
{
}
void CItem::SetItemText(const CString& strItem)
{
m_strName = strItem;
}
CString CItem::GetTipText()
{
return CString("Some Text");
}
void CItem::SetPercentage(UINT nPercentage)
{
if (nPercentage > m_nHiWaterMark)
m_nHiWaterMark = nPercentage;
m_nPercentage = nPercentage;
}
void CItem::Unselect()
{
if (m_bSelect == TRUE)
{
m_bSelect = FALSE;
m_pWnd->InvalidateRect(NULL,FALSE);
}
}
void CItem::Select()
{
if (m_bSelect == FALSE)
{
m_bSelect = TRUE;
m_pWnd->InvalidateRect(NULL,FALSE);
}
}
CRect CItem::GetBoundingRect()
{
CRect rc;
if (GetLogicalPos())
rc.UnionRect(CRect(0,m_rcText.top,LeftMargin,m_rcText.bottom),m_rcText);
return rc;
}
void CItem::SetOrdinal(int nPos)
{
m_nOrdinal = nPos;
}
void CItem::Invalidate()
{
m_pWnd->InvalidateRect(m_rcBounds,FALSE);
}
BOOL CItem::GetLogicalPos()
{
UINT nItems = m_pWnd->GetItemsPerPage();
UINT nScrollPos = m_pWnd->GetScrollPos();
// Is item on this page
if ((UINT) m_nOrdinal >= nScrollPos && (UINT)m_nOrdinal < (nScrollPos + nItems))
{
int nLogPos = m_nOrdinal - nScrollPos;
int nY = (nLogPos * BarSize) + TopLine;
// Set up the Rects
// TextRect | Bar Rect | Graph Rect
CRect rcClient;
m_pWnd->GetClientRect(rcClient);
m_rcGraph = rcClient;
m_rcGraph.top = nY;
m_rcGraph.bottom = nY+BarSize;
m_rcGraph.right -= RightMargin;
m_rcGraph.left = m_rcGraph.right - GraphWidth;
int nWidth = rcClient.Width() - GraphWidth;
CRect rcTotal;
// Rectangle for bar
rcTotal.SetRect(0,nY,nWidth,nY+BarSize);
rcTotal.left += LeftMargin;
rcTotal.right -= RightMargin;
// Rectangle for bar
m_rcBar = rcTotal;
m_rcBar.bottom = m_rcBar.top + m_rcBar.Height();
// Rectangle for text
m_rcText= rcTotal;
m_rcText.left = 4 + 16;
m_rcText.right = LeftMargin - 14;
return TRUE;
}
return FALSE;
}
void CItem::Draw(CDC* pDC)
{
//////////////////////////////////
// Draw Out the percentage bar
//////////////////////////////////
if (GetLogicalPos())
{
DrawBar(pDC);
DrawGraph(pDC);
CFont* pOldFont = pDC->SelectObject(m_bSelect ? m_pWnd->GetBoldFont() : m_pWnd->GetFont());
//////////////////////////////////
// Draw out Text
//////////////////////////////////
pDC->SetTextColor( RGB (255, 255, 255) );
pDC->SetBkMode(TRANSPARENT);
pDC->DrawText(m_strName,m_rcText,DT_SINGLELINE|DT_VCENTER|DT_LEFT|DT_END_ELLIPSIS);
pDC->SelectObject(pOldFont);
}
}
void CItem::DrawGraph(CDC* pDC)
{
CPen procpen(PS_SOLID,1,RGB(0,255,0));
CPen* pPen = pDC->SelectObject(&procpen);
int nX = m_rcGraph.left;
int nFrac = 4;
int nInc = 0;
pDC->SetROP2(R2_MERGEPEN);
for (int i = MAX_POINTS-(MAX_POINTS/nFrac); i < MAX_POINTS;i++)
{
int nPos = int((m_rcGraph.Height() * m_lStats[i]) / 100.0);
double dInc = (m_rcGraph.Width() * nInc) / MAX_POINTS;
nInc+=nFrac;
if (i == MAX_POINTS-(MAX_POINTS/nFrac))
pDC->MoveTo(nX,m_rcGraph.bottom - nPos);
else
pDC->LineTo((int)((double)nX+dInc),m_rcGraph.bottom - nPos);
}
pDC->SelectObject(pPen);
}
void CItem::DrawBar(CDC* pDC)
{
CRect rc;
CFont* pOldFont;
int nPercent = GetPercentage();
if (nPercent > 0)
{
double lFill = m_rcBar.Width() * nPercent /100.0;
pDC->SetBkMode(TRANSPARENT);
CString strNum;
CString strFormat;
pOldFont = pDC->SelectObject(m_pWnd->GetSmallFont());
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
rc = m_rcBar;
rc.right = (int)((double)m_rcBar.left + lFill);
if (GetPercentage() > 1)
strFormat = "%d%%";
else
strFormat = "%d";
strNum.Format(strFormat,GetPercentage());
pDC->SetTextColor(RGB(0,0,0));
rc.InflateRect(1,0);
pDC->Draw3dRect(rc,GetSysColor(COLOR_3DLIGHT),GetSysColor(COLOR_3DSHADOW));
rc.DeflateRect(1,0);
DrawGradientFill(pDC, &rc, 100, RGB(255,255,255), RGB(0,0,255) , TRUE ,&m_rcBar);
pDC->SelectObject(m_pWnd->GetFont());
CRect trc(rc);
pDC->DrawText(strNum,trc,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
}
////////////////////////////////////////////
// Draw in high water mark for this item
////////////////////////////////////////////
if (m_nHiWaterMark)
{
long lPosition = MulDiv(m_rcBar.Width(), m_nHiWaterMark, 100);
CPen pen;
pen.CreatePen(PS_SOLID,3,GetSysColor(COLOR_3DLIGHT));
CPen* pPenOld = pDC->SelectObject(&pen);
rc = m_rcBar;
rc.right = m_rcBar.left + lPosition;
rc.DeflateRect(-1,4);
pDC->MoveTo(rc.right,rc.top);
pDC->LineTo(rc.right,rc.bottom);
pDC->SelectObject(pPenOld);
}
}
UINT CItem::GetPercentage()
{
return m_nPercentage;
}
void DrawGradientFill(CDC* pDC, CRect* prc, int nSegs,
COLORREF crStart, COLORREF crEnd, BOOL bSemiFormat, CRect* prcFull)
{
// Get the starting RGB values and calculate the incremental
// changes to be applied.
COLORREF cr;
int iR = GetRValue(crStart);
int iG = GetGValue(crStart);
int iB = GetBValue(crStart);
int ieB = GetBValue(crEnd);
int ieG = GetGValue(crEnd);
int ieR = GetRValue(crEnd);
int iSegments = nSegs;
int iColorSegments = nSegs;
if(iSegments > prc->Width())
{
iSegments = prc->Width();
iColorSegments = iSegments;
}
if (bSemiFormat)
{
iColorSegments = nSegs;
if (iColorSegments > prcFull->Width())
iColorSegments = prcFull->Width();
}
int iDiffR = (ieR - iR);
int iDiffG = (ieG - iG);
int iDiffB = (ieB - iB);
int idR = 256 * (iDiffR) / (max(iColorSegments,1));
int idG = 256 * (iDiffG) / (max(iColorSegments,1));
int idB = 256 * (iDiffB) / (max(iColorSegments,1));
iR *= 256;
iG *= 256;
iB *= 256;
ieR *= 256;
ieG *= 256;
ieB *= 256;
int icx = prc->Width() / max(iSegments,1);
if (bSemiFormat)
{
icx = prcFull->Width() / max(iColorSegments,1);
}
int iLeft = prc->left;
int iRight;
pDC->SelectStockObject(NULL_PEN);
for (int i = 0; i < iSegments; i++, iR += idR, iG += idG, iB += idB)
{
// Use special code for the last segment to avoid any problems
// with integer division.
if (i == (iSegments - 1))
{
iRight = prc->right;
}
else
{
iRight = iLeft + icx;
if (bSemiFormat &&
iRight > prc->right)
iRight = prc->right;
}
cr = RGB(iR / 256, iG / 256, iB / 256);
{
// Perform the drawing and restore the DC; the objects
// will be freed automatically.
CBrush br(cr);
CBrush* pbrOld = pDC->SelectObject(&br);
pDC->Rectangle(iLeft, prc->top, iRight + 1, prc->bottom);
pDC->SelectObject(pbrOld);
}
// Reset the left side of the drawing rectangle.
iLeft = iRight;
}
}