示例#1
0
void CKademlia::StatsAddClosestDistance(CUInt128 uDist){
	if (uDist.Get32BitChunk(0) > 0){
		uint32_t nToAdd = (0xFFFFFFFF / uDist.Get32BitChunk(0)) / 2;
		if (m_liStatsEstUsersProbes.Find(nToAdd) == NULL)
			m_liStatsEstUsersProbes.AddHead(nToAdd);
	}
	if (m_liStatsEstUsersProbes.GetCount() > 100)
		m_liStatsEstUsersProbes.RemoveTail();
}
示例#2
0
void CKademlia::StatsAddClosestDistance(const CUInt128& distance)
{
	if (distance.Get32BitChunk(0) > 0) {
		uint32_t toAdd = (0xFFFFFFFF / distance.Get32BitChunk(0)) / 2;
		std::list<uint32_t>::iterator it = m_statsEstUsersProbes.begin();
		for (; it != m_statsEstUsersProbes.end(); ++it) {
			if (*it == toAdd) {
				break;
			}
		}
		if (it == m_statsEstUsersProbes.end()) {
			m_statsEstUsersProbes.push_front(toAdd);
		}
	}
	if (m_statsEstUsersProbes.size() > 100) {
		m_statsEstUsersProbes.pop_back();
	}
}
示例#3
0
void CKadLookupGraph::OnPaint()
{
	m_aNodesDrawRects.RemoveAll();
	CPaintDC pdc(this);

	CRect rcClnt;
	GetClientRect(&rcClnt);
	if (rcClnt.IsRectEmpty())
		return;

	CMemDC dc(&pdc, rcClnt);
	CPen* pOldPen = dc.SelectObject(&m_penAxis);
	if (g_xpStyle.IsThemeActive() && g_xpStyle.IsAppThemed())
	{
		HTHEME hTheme = g_xpStyle.OpenThemeData(NULL, L"ListView");
		if (hTheme)
		{
			g_xpStyle.DrawThemeBackground(hTheme, dc.m_hDC, 3, 0, &rcClnt, NULL);
			g_xpStyle.CloseThemeData(hTheme);
		}
	}
	else
	{
		dc.Rectangle(&rcClnt);
	}
	rcClnt.DeflateRect(1, 1, 1, 1);
	dc.FillSolidRect(rcClnt, GetSysColor(COLOR_WINDOW));
	rcClnt.DeflateRect(1, 1, 1, 1);
	COLORREF crOldTextColor = dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));

	CFont* pOldFont = dc.SelectObject(AfxGetMainWnd()->GetFont());
	if (!m_bInitializedFontMetrics)
	{
		TEXTMETRIC tm;
		dc.GetTextMetrics(&tm);
		// why is 'tm.tmMaxCharWidth' and 'tm.tmAveCharWidth' that wrong?
		CRect rcLabel;
		dc.DrawText(_T("888"), 3, &rcLabel, DT_CALCRECT);
		m_iMaxNumLabelWidth = rcLabel.Width();
		if (m_iMaxNumLabelWidth <= 0)
			m_iMaxNumLabelWidth = 3*8;
		m_iMaxLabelHeight = tm.tmHeight;
		if (m_iMaxLabelHeight <= 0)
			m_iMaxLabelHeight = 8;
		m_bInitializedFontMetrics = true;
	}

	int iLeftBorder = 3;
	int iRightBorder = 8;
	int iTopBorder = m_iMaxLabelHeight;
	int iBottomBorder = m_iMaxLabelHeight;

	int iBaseLineX = iLeftBorder;
	int iBaseLineY = rcClnt.bottom - iBottomBorder;
	UINT uHistWidth = rcClnt.Width() - iLeftBorder - iRightBorder;
	UINT uHistHeight = rcClnt.Height() - iTopBorder - iBottomBorder;
	if (uHistHeight == 0) {
		dc.SelectObject(pOldFont);
		dc.SetTextColor(crOldTextColor);
		return;
	}


	dc.MoveTo(iBaseLineX, rcClnt.top + iTopBorder);
	dc.LineTo(iBaseLineX, iBaseLineY);
	dc.LineTo(iBaseLineX + uHistWidth, iBaseLineY);

	dc.SelectObject(&m_penAux);

	CRect rcLabel(rcClnt);
	rcLabel.left = iBaseLineX;
	rcLabel.bottom = m_iMaxLabelHeight;
	dc.DrawText(m_strYaxis, m_strYaxis.GetLength(), &rcLabel, DT_LEFT | DT_TOP | DT_NOCLIP);

	rcLabel = rcClnt;
	rcLabel.top = rcClnt.bottom - m_iMaxLabelHeight + 1;
	dc.DrawText(m_strXaxis, m_strXaxis.GetLength(), &rcLabel, DT_RIGHT | DT_BOTTOM | DT_NOCLIP);

	if (m_pLookupHistory != NULL && m_pLookupHistory->GetHistoryEntries().GetCount() >= 1)
	{
		// How many nodes can we show without scrolling?
		sint32 uMaxNodes = uHistWidth / NODE_ENTRY_WIDTH;
		uint32 uNodeEntryWidth = 0;
		if (m_pLookupHistory->GetHistoryEntries().GetCount() > uMaxNodes /*|| !m_pLookupHistory->IsSearchStopped()*/)
			uNodeEntryWidth = NODE_ENTRY_WIDTH; // While the search is running, use a fixed width
		else
			uNodeEntryWidth = uHistWidth / m_pLookupHistory->GetHistoryEntries().GetCount(); // when the search is finished, use all available screen space

		sint32 iVisibleNodes = min(uMaxNodes, m_pLookupHistory->GetHistoryEntries().GetCount());

		// Set the scaling. 3 times the highest distance of the 1/3 closest nodes is the max distance
		CArray<CUInt128> aClosest;
		for (int i = 1; i <= iVisibleNodes; i++)
		{
			if (aClosest.GetCount() < ((iVisibleNodes / 3 == 0) ? 1 : (iVisibleNodes / 3)))
				aClosest.Add(m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - i]->m_uDistance);
			else
			{
				int iReplace = -1;
				for (int j = 0; j < aClosest.GetCount(); j++)
				{
					if ((iReplace == (-1) && aClosest[j] > m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - i]->m_uDistance)
						|| (iReplace >= 0 && aClosest[j] > aClosest[iReplace]))
					{
						iReplace = j;
					}
				}
				if (iReplace >= 0)
					aClosest[iReplace] = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - i]->m_uDistance;
			}
		}
		CUInt128 uTmpScalingDistance((ULONG)0);
		for (int j = 0; j < aClosest.GetCount(); j++)
		{
			if (aClosest[j] > uTmpScalingDistance)
				uTmpScalingDistance = aClosest[j];
		}
		// Convert it to uint64 by cutting of the less significant bits for easier and fast calculating
		uint64 uScalingDistance = 0;
		uint8 byStartChunk;
		for (byStartChunk = 0;  byStartChunk < 3; byStartChunk++)
		{
			if (uTmpScalingDistance.Get32BitChunk(byStartChunk) > 0)
			{
				uScalingDistance = ((uint64)uTmpScalingDistance.Get32BitChunk(byStartChunk) << 32) + (uint64)uTmpScalingDistance.Get32BitChunk(byStartChunk + 1);
				break;
			}
		}
		if (uScalingDistance == 0)
		{
			byStartChunk = 2;
			uScalingDistance = uTmpScalingDistance.Get32BitChunk(3);
		}
		uScalingDistance /= (uHistHeight - NODE_ENTRY_HEIGHT);
		uScalingDistance *= 3;
		ASSERT(uScalingDistance > 0);
		if (uScalingDistance == 0)
			uScalingDistance = 1;


		//if (m_bDbgLog)
		//	AddDebugLogLine(false, _T("KadGraph: Considering %u of %u Nodes, 1/3 Max Distance found: %s"), iVisibleNodes, m_pLookupHistory->GetHistoryEntries().GetCount(), uTmpScalingDistance.ToHexString());  

		CUInt128 uMaxScalingDistance(uTmpScalingDistance);
		uMaxScalingDistance.Add(uTmpScalingDistance);
		uMaxScalingDistance.Add(uTmpScalingDistance);

		// wow, what a mess, now lets collect drawing points
		for (int i = 1; i <= iVisibleNodes; i++)
		{
			CUInt128 uTmpDist = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - i]->m_uDistance;
			uint64 uDrawYPos;
			if (uTmpDist > uMaxScalingDistance)
				uDrawYPos = iTopBorder;
			else
			{
				uDrawYPos = (((uint64)uTmpDist.Get32BitChunk(byStartChunk) << 32) + (uint64)uTmpDist.Get32BitChunk(byStartChunk + 1));
				if (uDrawYPos > 0)
					uDrawYPos /= uScalingDistance;
				uDrawYPos = (iBaseLineY - NODE_ENTRY_HEIGHT) - uDrawYPos;
			}
			//if (m_bDbgLog)
			//	AddDebugLogLine(false, _T("KadGraph: Drawing Node %u of %u, Distance: %s, Y-Pos: %u"), (iVisibleNodes - i) + 1, iVisibleNodes, uTmpDist.ToHexString(), uDrawYPos); 

			ASSERT( uDrawYPos <= (uHistHeight) );
			uint32 nXOffset = 0;
			//if (uMaxNodes > iVisibleNodes && !m_pLookupHistory->IsSearchStopped()) // Fixed width for ongoing searches
			//	nXOffset = NODE_ENTRY_WIDTH * (uMaxNodes - iVisibleNodes);
			CPoint pointNode(uHistWidth - nXOffset - (i * uNodeEntryWidth), (uint32)uDrawYPos);
			m_aNodesDrawRects.Add(CRect(pointNode, CSize(NODE_ENTRY_WIDTH, NODE_ENTRY_HEIGHT)));
		}
		ASSERT( iVisibleNodes == m_aNodesDrawRects.GetCount() );

		// find HotItem (if any)
		m_iHotItemIdx = (-1);
		CPoint ptCursor;
		if (GetCursorPos(&ptCursor))
		{
			CRect rectWnd;
			GetWindowRect(&rectWnd);
			if (rectWnd.PtInRect(ptCursor))
			{
				ScreenToClient(&ptCursor);
				m_iHotItemIdx = CheckHotItem(ptCursor);
			}
		}
		m_pToolTip->Activate(m_iHotItemIdx >= 0 ? TRUE : FALSE);
		UpdateToolTip();

		CArray<bool> abHotItemConnected;
		if (m_iHotItemIdx >= 0)
		{
			abHotItemConnected.SetSize(iVisibleNodes);
			for (int i = 0; i < iVisibleNodes; i++)
				abHotItemConnected[i] = (m_iHotItemIdx == i);
		}
		// start drawing, beginning with the arrowClines connecting the nodes
		// if possible use GDI+ for Anti Aliasing
		extern bool g_bGdiPlusInstalled;
		ULONG_PTR gdiplusToken = 0;	
		Gdiplus::GdiplusStartupInput gdiplusStartupInput;
		if (g_bGdiPlusInstalled && Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) == Gdiplus::Ok)
		{
			{
				Gdiplus::Graphics gdipGraphic(dc);
				gdipGraphic.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
				Gdiplus::AdjustableArrowCap gdipArrow(6, 4);
				Gdiplus::Pen gdipPenGray(Gdiplus::Color(192, 192, 192), 0.8f);
				gdipPenGray.SetCustomEndCap(&gdipArrow);
				Gdiplus::Pen gdipPenDarkGray(Gdiplus::Color(100, 100, 100), 0.8f);
				gdipPenDarkGray.SetCustomEndCap(&gdipArrow);
				Gdiplus::Pen gdipPenRed(Gdiplus::Color(255, 32, 32), 0.8f);
				gdipPenRed.SetCustomEndCap(&gdipArrow);

				for (int i = 0; i < iVisibleNodes; i++)
				{
					const CLookupHistory::SLookupHistoryEntry* sEntry = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - (i + 1)];
					for (int j = 0; j < sEntry->m_liReceivedFromIdx.GetCount(); j++)
					{
						int iIdx = sEntry->m_liReceivedFromIdx[j];
						if (iIdx >= m_pLookupHistory->GetHistoryEntries().GetCount() - iVisibleNodes)
						{
							CPoint pFrom = m_aNodesDrawRects[m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1)].CenterPoint();
							CPoint pointTo = m_aNodesDrawRects[i].CenterPoint();

							Gdiplus::Pen* pen;
							if (m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1) == m_iHotItemIdx)
							{
								abHotItemConnected[i] = true;
								pen = &gdipPenRed;
							}
							else if (i == m_iHotItemIdx)
							{
								abHotItemConnected[m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1)] = true;
								pen = &gdipPenDarkGray;
							}
							else
								pen = &gdipPenGray;

							gdipGraphic.DrawLine(pen, pFrom.x, pFrom.y, pointTo.x, pointTo.y);
						}
					}
				}
			}
			Gdiplus::GdiplusShutdown(gdiplusToken);
		}
		else
		{
			for (int i = 0; i < iVisibleNodes; i++)
			{
				const CLookupHistory::SLookupHistoryEntry* sEntry = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - (i + 1)];
				for (int j = 0; j < sEntry->m_liReceivedFromIdx.GetCount(); j++)
				{
					int iIdx = sEntry->m_liReceivedFromIdx[j];
					if (iIdx >= m_pLookupHistory->GetHistoryEntries().GetCount() - iVisibleNodes)
					{

						CPoint pFrom = m_aNodesDrawRects[m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1)].CenterPoint();
						CPoint pointTo = m_aNodesDrawRects[i].CenterPoint();

						if (m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1) == m_iHotItemIdx)
						{
							abHotItemConnected[i] = true;
							dc.SelectObject(&m_penRed);
						}
						else
						{
							if (i == m_iHotItemIdx)
								abHotItemConnected[m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1)] = true;
							dc.SelectObject(&m_penAux);
						}

						POINT aptPoly[3];
						POINT pBase;
						float vecLine[2];
						float vecLeft[2];
						int nWidth = 4;

						// set to point
						aptPoly[0].x = pointTo.x;
						aptPoly[0].y = pointTo.y;

						// build the line vector
						vecLine[0] = (float) aptPoly[0].x - pFrom.x;
						vecLine[1] = (float) aptPoly[0].y - pFrom.y;

						// build the arrow base vector - normal to the line
						vecLeft[0] = -vecLine[1];
						vecLeft[1] = vecLine[0];

						// setup length parameters
						float fLength = (float) sqrt(vecLine[0] * vecLine[0] + vecLine[1] * vecLine[1]);
						float th = nWidth / (2.0f * fLength);
						float ta = nWidth / (2.0f * (tanf(0.3f) / 2.0f) * fLength);

						// find the base of the arrow
						pBase.x = (int) (aptPoly[0].x + -ta * vecLine[0]);
						pBase.y = (int) (aptPoly[0].y + -ta * vecLine[1]);

						// build the points on the sides of the arrow
						aptPoly[1].x = (int) (pBase.x + th * vecLeft[0]);
						aptPoly[1].y = (int) (pBase.y + th * vecLeft[1]);
						aptPoly[2].x = (int) (pBase.x + -th * vecLeft[0]);
						aptPoly[2].y = (int) (pBase.y + -th * vecLeft[1]);
						dc.MoveTo(pFrom);
						dc.LineTo(aptPoly[0].x, aptPoly[0].y);
						dc.Polygon(aptPoly, 3);
					}
				}
			}
		}

		// draw the nodes images
		for (int i = 0; i < iVisibleNodes; i++)
		{
			CPoint pointNode = m_aNodesDrawRects[i].CenterPoint();
			pointNode.x -= 8;
			pointNode.y -= 8;

			uint8 byIconIdx = 0;
			const CLookupHistory::SLookupHistoryEntry* sEntry = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - (i + 1)];
			if (sEntry->m_dwAskedContactsTime > 0)
			{
				if (sEntry->m_uRespondedContact > 0)
					byIconIdx = sEntry->m_bProvidedCloser ? 0 : 1; // green or blue
				else if (sEntry->m_dwAskedContactsTime + SEC2MS(3) < ::GetTickCount())
					byIconIdx = 3; // red
				else
					byIconIdx = 2; // yellow

			}
			else if (sEntry->m_bForcedInteresting)
				byIconIdx = 2;
			else
				ASSERT( false );

			if (m_iHotItemIdx >= 0 && !abHotItemConnected[i])
				m_iml.DrawEx(&dc, byIconIdx, pointNode, CSize(0, 0), CLR_NONE, GetSysColor(COLOR_WINDOW), ILD_BLEND50);
			else	
				m_iml.Draw(&dc, byIconIdx, pointNode, ILD_NORMAL);
				

			if (sEntry->m_dwAskedSearchItemTime > 0)
			{
				// Draw the Icon indicating that we asked this Node for results
				// enough space above? if not below
				CPoint pointIndicator = pointNode;
				if (pointIndicator.y - 16 - 4 >= iTopBorder)
					pointIndicator.y -= 20;
				else
					pointIndicator.y += 20;
				
				switch (m_pLookupHistory->GetType())
				{
					case Kademlia::CSearch::FILE:
					case Kademlia::CSearch::KEYWORD:
					case Kademlia::CSearch::NOTES:
					{
						int nOverlayImage = 0;
						if (sEntry->m_uRespondedSearchItem > 0)
							nOverlayImage = 1;
						else if (sEntry->m_dwAskedSearchItemTime + SEC2MS(5) < ::GetTickCount())
							nOverlayImage = 2;
						m_iml.Draw(&dc, 4, pointIndicator, ILD_NORMAL | INDEXTOOVERLAYMASK(nOverlayImage));
						break;
					}
					case Kademlia::CSearch::STOREFILE:
						m_iml.Draw(&dc, 6, pointIndicator, ILD_NORMAL);
						break;
					case Kademlia::CSearch::STOREKEYWORD:
					case Kademlia::CSearch::STORENOTES:
						m_iml.Draw(&dc, 5, pointIndicator, ILD_NORMAL);
						break;

					/* Nothing to show
					case CSearch::NODE:
					case CSearch::NODECOMPLETE:
					case CSearch::NODESPECIAL:
					case CSearch::NODEFWCHECKUDP:
					case CSearch::FINDBUDDY:
					default:*/
				}
			}
		}
	}
	m_bDbgLog = false;
	dc.SelectObject(pOldPen);
	dc.SelectObject(pOldFont);
	dc.SetTextColor(crOldTextColor);
}