Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
5.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // GraphControl.cpp : implementation file
  9. //
  10. #include "stdafx.h"
  11. #include "vmpi_browser_job_watch.h"
  12. #include "GraphControl.h"
  13. #include "mathlib/mathlib.h"
  14. #ifdef _DEBUG
  15. #define new DEBUG_NEW
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CGraphControl
  21. CGraphControl::CGraphControl()
  22. {
  23. }
  24. CGraphControl::~CGraphControl()
  25. {
  26. }
  27. BEGIN_MESSAGE_MAP(CGraphControl, CWnd)
  28. //{{AFX_MSG_MAP(CGraphControl)
  29. ON_WM_PAINT()
  30. //}}AFX_MSG_MAP
  31. END_MESSAGE_MAP()
  32. void CGraphControl::Clear()
  33. {
  34. CRect rcClient;
  35. GetClientRect( rcClient );
  36. CDC *pDC = GetDC();
  37. CBrush brush( RGB( 0, 0, 0 ) );
  38. CBrush *pOldBrush = pDC->SelectObject( &brush );
  39. pDC->Rectangle( 0, 0, rcClient.Width(), rcClient.Height() );
  40. pDC->SelectObject( pOldBrush );
  41. ReleaseDC( pDC );
  42. }
  43. void CGraphControl::Render( CDC *pDC )
  44. {
  45. // Clear the background.
  46. CRect rcClient;
  47. GetClientRect( rcClient );
  48. CBrush brush( RGB( 0, 0, 0 ) );
  49. CBrush *pOldBrush = pDC->SelectObject( &brush );
  50. pDC->Rectangle( 0, 0, rcClient.Width(), rcClient.Height() );
  51. pDC->SelectObject( pOldBrush );
  52. // Work backwards from the right side to the left.
  53. int nIntervals = rcClient.Width();
  54. DWORD intervalMS = 500; // one interval per pixel
  55. DWORD startTime = 0xFFFFFFFF, endTime = 0;
  56. // First, find which order of magnitude to use on the vertical scale by finding the maximum value.
  57. for ( int iEntry=0; iEntry < m_Entries.Count(); iEntry++ )
  58. {
  59. DWORD msTime = m_Entries[iEntry].m_msTime;
  60. startTime = min( startTime, msTime );
  61. endTime = max( endTime, msTime );
  62. }
  63. int curTime = (int)endTime - nIntervals*intervalMS;
  64. CGraphEntry prevEntry, curEntry;
  65. prevEntry.m_msTime = curEntry.m_msTime = -1;
  66. CUtlVector<POINT> sentPoints;
  67. CUtlVector<POINT> receivedPoints;
  68. int iCurEntry = -1;
  69. int nMaxBytesSent = -1, nMaxBytesReceived = -1;
  70. for ( int x=0; x < nIntervals; x++ )
  71. {
  72. if ( curTime >= 0 )
  73. {
  74. // Now find the graph_entry for the time we're at.
  75. while ( prevEntry.m_msTime == -1 || curTime > curEntry.m_msTime )
  76. {
  77. ++iCurEntry;
  78. if ( iCurEntry >= m_Entries.Count() )
  79. goto ENDLOOP;
  80. prevEntry = curEntry;
  81. curEntry = m_Entries[iCurEntry];
  82. }
  83. if ( curTime >= prevEntry.m_msTime && curTime <= curEntry.m_msTime )
  84. {
  85. // Interpolate the bytes sent.
  86. int nBytesSent = (int)RemapVal(
  87. curTime,
  88. prevEntry.m_msTime, curEntry.m_msTime,
  89. prevEntry.m_nBytesSent, curEntry.m_nBytesSent );
  90. POINT sentPoint = { x, nBytesSent };
  91. sentPoints.AddToTail( sentPoint );
  92. nMaxBytesSent = max( nMaxBytesSent, nBytesSent );
  93. int nBytesReceived = (int)RemapVal(
  94. curTime,
  95. prevEntry.m_msTime, curEntry.m_msTime,
  96. prevEntry.m_nBytesReceived, curEntry.m_nBytesReceived );
  97. POINT receivedPoint = { x, nBytesReceived };
  98. receivedPoints.AddToTail( receivedPoint );
  99. nMaxBytesReceived = max( nMaxBytesReceived, nBytesReceived );
  100. }
  101. }
  102. curTime += intervalMS;
  103. }
  104. ENDLOOP:;
  105. // Now normalize all the values.
  106. int largest = max( nMaxBytesSent, nMaxBytesReceived );
  107. int topValue = (largest*11) / 10;
  108. /*
  109. DWORD nZeros;
  110. for( nZeros = 1; nZeros < 20; nZeros++ )
  111. {
  112. if ( largest < pow( 10, nZeros ) )
  113. break;
  114. }
  115. // Now find the value at the top of the graph. We choose the smallest enclosing tenth of the
  116. // order of magnitude we're at (so if we were at 1,000,000, and our max value was 350,000, we'd choose 400,000).
  117. int iTenth;
  118. int topValue;
  119. for ( iTenth=1; iTenth <= 10; iTenth++ )
  120. {
  121. topValue = (DWORD)( pow( 10, nZeros-1 ) * iTenth );
  122. if ( topValue >= largest )
  123. break;
  124. }
  125. */
  126. for ( int iSample=0; iSample < sentPoints.Count(); iSample++ )
  127. {
  128. double flHeight;
  129. flHeight = ((double)sentPoints[iSample].y / topValue) * (rcClient.Height() - 1);
  130. sentPoints[iSample].y = (int)( rcClient.Height() - flHeight );
  131. flHeight = ((double)receivedPoints[iSample].y / topValue) * (rcClient.Height() - 1);
  132. receivedPoints[iSample].y = (int)( rcClient.Height() - flHeight );
  133. }
  134. // Draw some horizontal lines dividing the space.
  135. int nLines = 10;
  136. for ( int iLine=0; iLine <= nLines; iLine++ )
  137. {
  138. CPen penLine;
  139. COLORREF color;
  140. if ( iLine == 0 || iLine == nLines/2 )
  141. color = RGB( 0, 220, 0 );
  142. else
  143. color = RGB( 0, 100, 0 );
  144. penLine.CreatePen( PS_SOLID, 1, color );
  145. CPen *pOldPen = pDC->SelectObject( &penLine );
  146. int y = (iLine * rcClient.Height()) / nLines;
  147. pDC->MoveTo( 0, y );
  148. pDC->LineTo( rcClient.Width(), y );
  149. pDC->SelectObject( pOldPen );
  150. }
  151. // Now draw the lines for the data.
  152. CPen penSent( PS_SOLID, 1, RGB( 0, 255, 0 ) );
  153. CPen *pOldPen = pDC->SelectObject( &penSent );
  154. pDC->Polyline( sentPoints.Base(), sentPoints.Count() );
  155. pDC->SelectObject( pOldPen );
  156. CPen penReceived( PS_SOLID, 1, RGB( 255, 255, 0 ) );
  157. pOldPen = pDC->SelectObject( &penReceived );
  158. pDC->Polyline( receivedPoints.Base(), receivedPoints.Count() );
  159. pDC->SelectObject( pOldPen );
  160. // Draw text labels.
  161. pDC->SetTextColor( RGB( 200, 200, 200 ) );
  162. pDC->SetBkColor( 0 );
  163. CString str;
  164. str.Format( "%dk", (topValue+511) / 1024 );
  165. pDC->ExtTextOut( 0, 1, 0, NULL, str, NULL );
  166. str.Format( "%dk", (topValue+511) / 1024 / 2 );
  167. pDC->ExtTextOut( 0, rcClient.Height()/2 + 1, 0, NULL, str, NULL );
  168. }
  169. void CGraphControl::Fill( CUtlVector<CGraphEntry> &entries )
  170. {
  171. CDC *pDC = GetDC();
  172. if ( !pDC )
  173. return;
  174. m_Entries = entries;
  175. Render( pDC );
  176. ReleaseDC( pDC );
  177. }
  178. /////////////////////////////////////////////////////////////////////////////
  179. // CGraphControl message handlers
  180. void CGraphControl::OnPaint()
  181. {
  182. CPaintDC dc(this); // device context for painting
  183. Render( &dc );
  184. }