⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graphline.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
字号:
//
// GraphLine.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "GraphLine.h"
#include "GraphItem.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define MIN_GRID_SIZE_HORZ	16
#define TOP_MARGIN			10


//////////////////////////////////////////////////////////////////////
// CLineGraph construction

CLineGraph::CLineGraph()
{
	m_bShowAxis		= TRUE;
	m_bShowGrid		= TRUE;
	m_bShowLegend	= TRUE;
	m_crBack		= 0;
	m_crGrid		= RGB( 0, 0, 128 );
	m_nMinGridVert	= 32;
	
	m_nSpeed		= 100;
	m_nScale		= 2;
	m_nMaximum		= 0;
	m_nUpdates		= 0;
	m_tLastScale	= 0;
}

CLineGraph::~CLineGraph()
{
	ClearItems();
}

//////////////////////////////////////////////////////////////////////
// CLineGraph list access

void CLineGraph::AddItem(CGraphItem* pItem)
{
	m_pItems.AddTail( pItem );
}

POSITION CLineGraph::GetItemIterator() const
{
	return m_pItems.GetHeadPosition();
}

CGraphItem* CLineGraph::GetNextItem(POSITION& pos) const
{
	return (CGraphItem*)m_pItems.GetNext( pos );
}

int CLineGraph::GetItemCount() const
{
	return m_pItems.GetCount();
}

void CLineGraph::RemoveItem(CGraphItem* pItem)
{
	POSITION pos = m_pItems.Find( pItem );
	if ( pos != NULL ) m_pItems.RemoveAt( pos );
	delete pItem;
}

void CLineGraph::ClearItems()
{
	for ( POSITION pos = GetItemIterator() ; pos ; )
	{
		delete GetNextItem( pos );
	}
	m_pItems.RemoveAll();
}

//////////////////////////////////////////////////////////////////////
// CLineGraph create default

void CLineGraph::CreateDefaults()
{
	AddItem( new CGraphItem( GRC_TOTAL_BANDWIDTH_IN, 0, RGB( 0, 255, 0 ) ) );
	AddItem( new CGraphItem( GRC_TOTAL_BANDWIDTH_OUT, 0, RGB( 255, 0, 0 ) ) );
}

//////////////////////////////////////////////////////////////////////
// CLineGraph update

BOOL CLineGraph::Update()
{
	DWORD tNow = GetTickCount();

	if ( tNow - m_tLastScale > 10000 )
	{
		m_tLastScale = tNow;
		ResetMaximum();
	}

	for ( POSITION pos = GetItemIterator() ; pos ; )
	{
		CGraphItem* pItem = GetNextItem( pos );
		DWORD nValue = pItem->Update();
		m_nMaximum = max( m_nMaximum, nValue );
	}

	m_nUpdates++;
	return m_pItems.GetCount();
}

//////////////////////////////////////////////////////////////////////
// CLineGraph clear

void CLineGraph::Clear()
{
	for ( POSITION pos = GetItemIterator() ; pos ; )
	{
		GetNextItem( pos )->Clear();
	}

	m_nMaximum = 0;
}

//////////////////////////////////////////////////////////////////////
// CLineGraph serialize

void CLineGraph::Serialize(CArchive& ar)
{
	if ( ar.IsStoring() )
	{
		ar << m_bShowAxis;
		ar << m_bShowGrid;
		ar << m_bShowLegend;
		ar << m_nSpeed;
		ar << m_nScale;

		ar.WriteCount( GetItemCount() );

		for ( POSITION pos = GetItemIterator() ; pos ; )
		{
			GetNextItem( pos )->Serialize( ar );
		}
	}
	else
	{
		ar >> m_bShowAxis;
		ar >> m_bShowGrid;
		ar >> m_bShowLegend;
		ar >> m_nSpeed;
		ar >> m_nScale;

		for ( int nCount = ar.ReadCount() ; nCount > 0 ; nCount-- )
		{
			CGraphItem* pItem = new CGraphItem();
			pItem->Serialize( ar );
			m_pItems.AddTail( pItem );
		}
	}
}

//////////////////////////////////////////////////////////////////////
// CLineGraph maximum rescale

void CLineGraph::ResetMaximum(BOOL bForce)
{
	DWORD nMaximum = 0;

	for ( POSITION pos = GetItemIterator() ; pos ; )
	{
		CGraphItem* pItem = GetNextItem( pos );
		DWORD nValue = pItem->GetMaximum();
		nMaximum = max( nMaximum, nValue );
	}
	
	if ( nMaximum || bForce ) m_nMaximum = nMaximum;
}

//////////////////////////////////////////////////////////////////////
// CLineGraph paint

void CLineGraph::Paint(CDC* pDC, CRect* pRect)
{
	if ( m_pGridPen.m_hObject == NULL ) m_pGridPen.CreatePen( PS_SOLID, 1, m_crGrid );

	DWORD nWidth = (DWORD)pRect->Width() / m_nScale + 2;

	if ( pRect->Width() > 64 )
	{
		for ( POSITION pos = GetItemIterator() ; pos ; )
		{
			CGraphItem* pItem = GetNextItem( pos );
			pItem->SetHistory( nWidth );
		}
	}

	pDC->FillSolidRect( pRect, m_crBack );

	if ( m_pItems.IsEmpty() || m_nMaximum == 0 ) return;

	CFont* pOldFont = (CFont*)pDC->SelectObject( &theApp.m_gdiFont );
	pDC->SetBkMode( TRANSPARENT );

	if ( m_bShowGrid ) PaintGrid( pDC, pRect );

	for ( POSITION pos = m_pItems.GetHeadPosition() ; pos ; )
	{
		CGraphItem* pItem = (CGraphItem*)m_pItems.GetNext( pos );
		
		DWORD nPoints	= min( pItem->m_nLength, nWidth );
		POINT* pPoints	= new POINT[ nPoints ];
		
		for ( DWORD nPos = 0 ; nPos < nPoints ; nPos++ )
		{
			DWORD nValue = pItem->GetValueAt( nPos );
			
			nValue = pRect->bottom - nValue * ( pRect->Height() - TOP_MARGIN ) / m_nMaximum;

			pPoints[ nPos ].x = pRect->right - nPos * m_nScale - 1;
			pPoints[ nPos ].y = nValue + 4;
		}
		
		pItem->MakeGradient( m_crBack );
		
		CPen* pOldPen = (CPen*)pDC->SelectObject( &pItem->m_pPen[3] );

		for ( int nLayer = 4 ; nLayer ; nLayer-- )
		{
			pDC->Polyline( pPoints, nPoints );

			if ( nLayer > 1 )
			{
				for ( DWORD nPos = 0 ; nPos < nPoints ; nPos++ ) pPoints[ nPos ].y --;
				pDC->SelectObject( &pItem->m_pPen[ nLayer - 2 ] );
			}
		}

		pDC->SelectObject( pOldPen );

		delete [] pPoints;
	}

	if ( m_bShowLegend ) PaintLegend( pDC, pRect );

	pDC->SelectObject( pOldFont );
}

void CLineGraph::PaintGrid(CDC* pDC, CRect* pRect)
{
	CPen* pOldPen = (CPen*)pDC->SelectObject( &m_pGridPen );

	if ( pRect->Height() <= TOP_MARGIN ) return;

	DWORD nScale = max( m_nScale, MIN_GRID_SIZE_HORZ );
	DWORD nCount = pRect->Width() / nScale + 1;
	DWORD nTimeB = nScale / m_nScale;

	int nX = pRect->right + m_nScale - ( m_nUpdates % nTimeB ) * m_nScale;

	for ( DWORD nPos = 0 ; nPos < nCount ; nPos++, nX -= nScale )
	{
		pDC->MoveTo( nX, pRect->top );
		pDC->LineTo( nX, pRect->bottom );
	}

	BOOL bVolume = FALSE;

	if ( m_bShowAxis )
	{
		for ( POSITION pos = GetItemIterator() ; pos && ! bVolume ; )
		{
			CGraphItem* pItem	= GetNextItem( pos );
			GRAPHITEM* pDesc	= pItem->GetItemDesc( pItem->m_nCode );
			if ( pDesc && pDesc->m_nUnits == 1 ) bVolume = TRUE;
		}
		pDC->SetTextColor( RGB( 193, 196, 255 ) );
	}

	nScale = m_nMinGridVert * m_nMaximum / ( pRect->Height() - TOP_MARGIN );
	if ( ! nScale  ) nScale = 1;

	int nOldY = pRect->bottom;

	for ( nPos = 1 ; ; nPos++ )
	{
		int nY = pRect->bottom - nScale * nPos * ( pRect->Height() - TOP_MARGIN ) / m_nMaximum;
		if ( nY < 0 || nY >= nOldY - 4 ) break;
		nOldY = nY;

		pDC->MoveTo( pRect->left, nY );
		pDC->LineTo( pRect->right, nY );

		if ( m_bShowAxis )
		{
			CString strValue;
			if ( bVolume )
				strValue = Settings.SmartVolume( nScale * nPos, FALSE, TRUE );
			else
				strValue.Format( _T("%lu"), nScale * nPos );
			pDC->ExtTextOut( pRect->left + 4, nY + 1, 0, NULL, strValue, NULL );
		}
	}

	pDC->SelectObject( pOldPen );
}

void CLineGraph::PaintLegend(CDC* pDC, CRect* pRect)
{
	int nHeight	= pDC->GetTextExtent( _T("Cy") ).cy;
	int nLeft	= pRect->left + ( pRect->Width() > 128 ) ? 64 : 0;
	int nTop	= pRect->top + 1;

	for ( POSITION pos = GetItemIterator() ; pos ; nTop += nHeight )
	{
		CGraphItem* pItem = GetNextItem( pos );
		pDC->SetTextColor( pItem->m_nColour );
		pDC->ExtTextOut( nLeft, nTop, 0, NULL, _T("

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -