Source code of Windows XP (NT5)
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.

219 lines
4.9 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. scale.cpp
  5. Abstract:
  6. Implements display of the scale numbers on the graph y-axis.
  7. --*/
  8. #include "polyline.h"
  9. #include <stdio.h>
  10. #define SCALE_MARGIN 10
  11. CGraphScale::CGraphScale( void )
  12. : m_iMaxValue(100),
  13. m_iMinValue(0),
  14. m_nTics(0),
  15. m_iTextHeight(0)
  16. {
  17. }
  18. CGraphScale::~CGraphScale( void )
  19. {
  20. }
  21. void CGraphScale::SetRect( PRECT pRect )
  22. {
  23. m_Rect = *pRect;
  24. SetTicPositions();
  25. }
  26. void CGraphScale::SetMaxValue( INT iMaxValue )
  27. {
  28. m_iMaxValue = iMaxValue;
  29. SetTicPositions();
  30. }
  31. void CGraphScale::SetMinValue( INT iMinValue )
  32. {
  33. m_iMinValue = iMinValue;
  34. SetTicPositions();
  35. }
  36. void CGraphScale::SetTicPositions( void )
  37. {
  38. INT iHeight;
  39. INT nMaxTics;
  40. INT i;
  41. CStepper stepper;
  42. static INT aiTicTable[] = {25,20,10,5,4,2,1,0};
  43. iHeight = m_Rect.bottom - m_Rect.top;
  44. if (!(iHeight > 0 && m_iTextHeight > 0)) {
  45. m_nTics = 0;
  46. return;
  47. }
  48. // Determine number of labels that will fit
  49. nMaxTics = iHeight / (m_iTextHeight + m_iTextHeight/2);
  50. for (i=0; nMaxTics < aiTicTable[i]; i++) {};
  51. m_nTics = aiTicTable[i];
  52. // Don't have more labels than values
  53. if (m_iMaxValue - m_iMinValue < m_nTics)
  54. m_nTics = m_iMaxValue - m_iMinValue;
  55. // Locate equally spaced tic marks
  56. if (m_nTics > 0)
  57. {
  58. m_aiTicPos[0] = 0;
  59. stepper.Init(iHeight,m_nTics);
  60. for (i = 1; i <= m_nTics; i++)
  61. {
  62. m_aiTicPos[i] = stepper.NextPosition();
  63. }
  64. }
  65. }
  66. INT CGraphScale::GetTicPositions( INT **piTics )
  67. {
  68. *piTics = m_aiTicPos;
  69. return m_nTics;
  70. }
  71. INT CGraphScale::GetWidth (HDC hDC)
  72. {
  73. TCHAR szMaxValue [20] ;
  74. SIZE Size;
  75. INT iWidth;
  76. // compute size of largest possible numerical label plus space
  77. if ( 0 != FormatNumber (
  78. (double)m_iMaxValue,
  79. szMaxValue,
  80. 20,
  81. eMinimumWidth,
  82. eFloatPrecision) ) {
  83. GetTextExtentPoint32(hDC, szMaxValue, lstrlen(szMaxValue), &Size);
  84. // Save Text height for tic calculations
  85. m_iTextHeight = Size.cy;
  86. iWidth = Size.cx + SCALE_MARGIN;
  87. } else {
  88. iWidth = 0;
  89. }
  90. return iWidth;
  91. }
  92. void CGraphScale::Draw (HDC hDC)
  93. {
  94. TCHAR szScale [20] ;
  95. INT iRetChars,
  96. i,
  97. iUnitsPerLine ;
  98. INT iRange;
  99. FLOAT ePercentOfTotal ;
  100. FLOAT eDiff ;
  101. BOOL bUseFloatingPt = FALSE ;
  102. RECT rectClip;
  103. // nTicks may be zero if the screen size if getting too small
  104. if (m_nTics < 1 || m_iMaxValue <= m_iMinValue)
  105. return;
  106. iRange = m_iMaxValue - m_iMinValue;
  107. // Calculate what percentage of the total each line represents.
  108. ePercentOfTotal = ((FLOAT) 1.0) / ((FLOAT) m_nTics) ;
  109. // Calculate the amount (number of units) of the Vertical max each
  110. // each line in the graph represents.
  111. iUnitsPerLine = (INT) ((FLOAT) iRange * ePercentOfTotal) ;
  112. ePercentOfTotal *= (FLOAT) iRange;
  113. eDiff = (FLOAT)iUnitsPerLine - ePercentOfTotal ;
  114. if (eDiff < (FLOAT) 0.0)
  115. eDiff = -eDiff ;
  116. if ( (iUnitsPerLine < 100)
  117. && (eDiff > (FLOAT) 0.1) ) {
  118. bUseFloatingPt = TRUE ;
  119. }
  120. SetTextAlign (hDC, TA_TOP | TA_RIGHT) ;
  121. rectClip.left = m_Rect.left;
  122. rectClip.right = m_Rect.right - SCALE_MARGIN;
  123. // Now Output each string.
  124. for (i = 0; i < m_nTics; i++) {
  125. if (bUseFloatingPt) {
  126. FLOAT fValue = (FLOAT)m_iMaxValue - ((FLOAT)i * ePercentOfTotal);
  127. iRetChars = FormatNumber (
  128. (double)fValue,
  129. szScale,
  130. 20,
  131. eMinimumWidth,
  132. eFloatPrecision);
  133. } else {
  134. iRetChars = _stprintf (szScale, TEXT("%d"),
  135. m_iMaxValue - (i * iUnitsPerLine)) ;
  136. }
  137. rectClip.top = m_aiTicPos[i] + m_Rect.top - m_iTextHeight/2;
  138. rectClip.bottom = rectClip.top + m_iTextHeight;
  139. ExtTextOut (
  140. hDC,
  141. rectClip.right,
  142. rectClip.top,
  143. 0,
  144. &rectClip,
  145. szScale,
  146. lstrlen(szScale),
  147. NULL );
  148. }
  149. // Make sure the last value is the specified Minimum.
  150. if (bUseFloatingPt) {
  151. iRetChars = FormatNumber (
  152. (double)m_iMinValue,
  153. szScale,
  154. 20,
  155. eMinimumWidth,
  156. eFloatPrecision);
  157. } else {
  158. iRetChars = _stprintf (szScale, TEXT("%d"), m_iMinValue) ;
  159. }
  160. rectClip.top = m_aiTicPos[i] + m_Rect.top - m_iTextHeight/2;
  161. rectClip.bottom = rectClip.top + m_iTextHeight;
  162. ExtTextOut (
  163. hDC,
  164. rectClip.right,
  165. rectClip.top,
  166. 0,
  167. &rectClip,
  168. szScale,
  169. lstrlen(szScale),
  170. NULL);
  171. }