Counter Strike : Global Offensive Source Code
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.

668 lines
17 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #define PROTECTED_THINGS_DISABLE
  8. #include <vgui/IBorder.h>
  9. #include <vgui/IInput.h>
  10. #include <vgui/ISystem.h>
  11. #include <vgui/IScheme.h>
  12. #include <vgui/ISurface.h>
  13. #include <vgui/MouseCode.h>
  14. #include <keyvalues.h>
  15. #include <vgui_controls/ScrollBarSlider.h>
  16. #include <vgui_controls/Controls.h>
  17. #include <math.h>
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include <tier0/memdbgon.h>
  20. using namespace vgui;
  21. //-----------------------------------------------------------------------------
  22. // The ScrollBarSlider is the scroll bar nob that moves up and down in through a range.
  23. //-----------------------------------------------------------------------------
  24. ScrollBarSlider::ScrollBarSlider(Panel *parent, const char *panelName, bool vertical) : Panel(parent, panelName)
  25. {
  26. _vertical=vertical;
  27. _dragging=false;
  28. _value=0;
  29. _range[0]=0;
  30. _range[1]=0;
  31. _rangeWindow=0;
  32. _buttonOffset=0;
  33. Q_memset( _ScrollBarSliderBorder, 0, sizeof( _ScrollBarSliderBorder ) );
  34. m_bCursorOver = false;
  35. RecomputeNobPosFromValue();
  36. SetBlockDragChaining( true );
  37. m_NobFocusColor = Color( 255, 255, 255, 255 );
  38. m_NobDragColor = Color( 255, 255, 255, 255 );
  39. m_nNobInset = 1;
  40. }
  41. //-----------------------------------------------------------------------------
  42. // Purpose: Set the size of the ScrollBarSlider nob
  43. //-----------------------------------------------------------------------------
  44. void ScrollBarSlider::SetSize(int wide,int tall)
  45. {
  46. BaseClass::SetSize(wide,tall);
  47. RecomputeNobPosFromValue();
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Whether the scroll bar is vertical (true) or not (false)
  51. //-----------------------------------------------------------------------------
  52. bool ScrollBarSlider::IsVertical()
  53. {
  54. return _vertical;
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Purpose: Set the ScrollBarSlider value of the nob.
  58. //-----------------------------------------------------------------------------
  59. void ScrollBarSlider::SetValue(int value)
  60. {
  61. int oldValue = _value;
  62. if (value > _range[1] - _rangeWindow)
  63. {
  64. // note our scrolling range must take into acount _rangeWindow
  65. value = _range[1] - _rangeWindow;
  66. }
  67. if (value < _range[0])
  68. {
  69. value = _range[0];
  70. }
  71. _value = value;
  72. RecomputeNobPosFromValue();
  73. if (_value != oldValue)
  74. {
  75. SendScrollBarSliderMovedMessage();
  76. }
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose: Get the ScrollBarSlider value of the nob.
  80. //-----------------------------------------------------------------------------
  81. int ScrollBarSlider::GetValue()
  82. {
  83. return _value;
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Purpose:
  87. //-----------------------------------------------------------------------------
  88. void ScrollBarSlider::PerformLayout()
  89. {
  90. RecomputeNobPosFromValue();
  91. BaseClass::PerformLayout();
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Purpose: Given the value of the ScrollBarSlider, adjust the ends of the nob.
  95. //-----------------------------------------------------------------------------
  96. void ScrollBarSlider::RecomputeNobPosFromValue()
  97. {
  98. int wide, tall;
  99. GetPaintSize(wide, tall);
  100. float fwide = (float)( wide - 1 );
  101. float ftall = (float)( tall - 1 );
  102. float frange = (float)(_range[1] -_range[0]);
  103. float fvalue = (float)(_value - _range[0]);
  104. float frangewindow = (float)(_rangeWindow);
  105. float fper = ( frange != frangewindow ) ? fvalue / ( frange-frangewindow ) : 0;
  106. if ( frangewindow > 0 )
  107. {
  108. if ( frange <= 0.0 )
  109. {
  110. frange = 1.0;
  111. }
  112. float width, length;
  113. if (_vertical)
  114. {
  115. width = fwide;
  116. length = ftall;
  117. }
  118. else
  119. {
  120. width = ftall;
  121. length = fwide;
  122. }
  123. // our size is proportional to frangewindow/frange
  124. // the scroll bar nob's length reflects the amount of stuff on the screen
  125. // vs the total amount of stuff we could scroll through in window
  126. // so if a window showed half its contents and the other half is hidden the
  127. // scroll bar's length is half the window.
  128. // if everything is on the screen no nob is displayed
  129. // frange is how many 'lines' of stuff we can display
  130. // frangewindow is how many 'lines' are in the display window
  131. // proportion of whole window that is on screen
  132. float proportion = frangewindow / frange;
  133. float fnobsize = length * proportion;
  134. if ( fnobsize < width ) fnobsize = (float)width;
  135. float freepixels = length - fnobsize;
  136. float firstpixel = freepixels * fper;
  137. _nobPos[0] = (int)( firstpixel );
  138. _nobPos[1] = (int)( firstpixel + fnobsize );
  139. if ( _nobPos[1] > length )
  140. {
  141. _nobPos[0] = (int)( length - fnobsize );
  142. _nobPos[1] = (int)length;
  143. }
  144. }
  145. Repaint();
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Purpose: Get the ScrollBarSlider value using the location of the nob ends.
  149. //-----------------------------------------------------------------------------
  150. void ScrollBarSlider::RecomputeValueFromNobPos()
  151. {
  152. int wide, tall;
  153. GetPaintSize(wide, tall);
  154. float fwide = (float)( wide - 1 );
  155. float ftall = (float)( tall - 1 );
  156. float frange = (float)( _range[1] - _range[0] );
  157. float fvalue = (float)( _value - _range[0] );
  158. float fnob = (float)_nobPos[0];
  159. float frangewindow = (float)(_rangeWindow);
  160. if ( frangewindow > 0 )
  161. {
  162. if ( frange <= 0.0 )
  163. {
  164. frange = 1.0;
  165. }
  166. // set local width and length
  167. float width, length;
  168. if ( _vertical )
  169. {
  170. width = fwide;
  171. length = ftall;
  172. }
  173. else
  174. {
  175. width = ftall;
  176. length = fwide;
  177. }
  178. // calculate the size of the nob
  179. float proportion = frangewindow / frange;
  180. float fnobsize = length * proportion;
  181. if ( fnobsize < width )
  182. {
  183. fnobsize = width;
  184. }
  185. // Our scroll bar actually doesnt scroll through all frange lines in the truerange, we
  186. // actually only scroll through frange-frangewindow number of lines so we must take that
  187. // into account when we calculate the value
  188. // convert to our local size system
  189. // Make sure we don't divide by zero
  190. if ( length - fnobsize == 0 )
  191. {
  192. fvalue = 0.0f;
  193. }
  194. else
  195. {
  196. fvalue = (frange - frangewindow) * ( fnob / ( length - fnobsize ) );
  197. }
  198. }
  199. // check to see if we should just snap to the bottom
  200. if (fabs(fvalue + _rangeWindow - _range[1]) < (0.01f * frange))
  201. {
  202. // snap to the end
  203. _value = _range[1] - _rangeWindow;
  204. }
  205. else
  206. {
  207. // Take care of rounding issues.
  208. _value = (int)( fvalue + _range[0] + 0.5);
  209. }
  210. // Clamp final result
  211. _value = ( _value < (_range[1] - _rangeWindow) ) ? _value : (_range[1] - _rangeWindow);
  212. if (_value < _range[0])
  213. {
  214. _value = _range[0];
  215. }
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Purpose: Check if the ScrollBarSlider can move through one or more pixels per
  219. // unit of its range.
  220. //-----------------------------------------------------------------------------
  221. bool ScrollBarSlider::HasFullRange()
  222. {
  223. int wide, tall;
  224. GetPaintSize(wide, tall);
  225. float frangewindow = (float)(_rangeWindow);
  226. float checkAgainst = 0;
  227. if(_vertical)
  228. {
  229. checkAgainst = (float)tall;
  230. }
  231. else
  232. {
  233. checkAgainst = (float)wide;
  234. }
  235. if ( frangewindow > 0 )
  236. {
  237. if( frangewindow <= ( checkAgainst + _buttonOffset ) )
  238. {
  239. return true;
  240. }
  241. }
  242. return false;
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Purpose: Inform other watchers that the ScrollBarSlider was moved
  246. //-----------------------------------------------------------------------------
  247. void ScrollBarSlider::SendScrollBarSliderMovedMessage()
  248. {
  249. // send a changed message
  250. PostActionSignal(new KeyValues("ScrollBarSliderMoved", "position", _value));
  251. }
  252. void ScrollBarSlider::SendScrollBarSliderReleasedMessage()
  253. {
  254. // send a released message
  255. PostActionSignal(new KeyValues("ScrollBarSliderReleased", "position", _value));
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Purpose: Return true if this slider is actually drawing itself
  259. //-----------------------------------------------------------------------------
  260. bool ScrollBarSlider::IsSliderVisible( void )
  261. {
  262. int itemRange = _range[1] - _range[0];
  263. // Don't draw nob, no items in list
  264. if ( itemRange <= 0 )
  265. return false ;
  266. // Not enough range
  267. if ( itemRange <= _rangeWindow )
  268. return false;
  269. return true;
  270. }
  271. static char const *g_pBorderStyles[ ScrollBarSlider::Slider_Count ] =
  272. {
  273. "ScrollBarSliderBorder",
  274. "ScrollBarSliderBorderHover",
  275. "ScrollBarSliderBorderDragging",
  276. };
  277. //-----------------------------------------------------------------------------
  278. // Purpose:
  279. //-----------------------------------------------------------------------------
  280. void ScrollBarSlider::ApplySchemeSettings(IScheme *pScheme)
  281. {
  282. BaseClass::ApplySchemeSettings(pScheme);
  283. SetFgColor(GetSchemeColor("ScrollBarSlider.FgColor", pScheme));
  284. SetBgColor(GetSchemeColor("ScrollBarSlider.BgColor", pScheme));
  285. SetNobFocusColor(GetSchemeColor("ScrollBarSlider.NobFocusColor", GetBgColor(), pScheme ));
  286. SetNobDragColor( GetSchemeColor("ScrollBarSlider.NobDragColor", GetBgColor(), pScheme ));
  287. IBorder *pButtonBorder = pScheme->GetBorder("ButtonBorder");
  288. IBorder *pSliderBorder = pScheme->GetBorder("ScrollBarSliderBorder");
  289. // Prefer the sliderborder, but use ButtonBorder as a fallback
  290. IBorder *pFallback = pSliderBorder ? pSliderBorder : pButtonBorder;
  291. for ( int i = 0; i < Slider_Count; ++i )
  292. {
  293. IBorder *pBorder = pScheme->GetBorder( g_pBorderStyles[ i ] );
  294. _ScrollBarSliderBorder[ i ] = pBorder ? pBorder : pFallback;
  295. }
  296. const char *resourceString = pScheme->GetResourceString( "ScrollBarSlider.Inset" );
  297. if ( resourceString )
  298. {
  299. int nValue = Q_atoi(resourceString);
  300. if (IsProportional())
  301. {
  302. nValue = scheme()->GetProportionalScaledValueEx(GetScheme(), nValue);
  303. }
  304. m_nNobInset = MAX( nValue, 0 );
  305. }
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose:
  309. //-----------------------------------------------------------------------------
  310. void ScrollBarSlider::Paint()
  311. {
  312. int wide,tall;
  313. GetPaintSize(wide,tall);
  314. if ( !IsSliderVisible() )
  315. return;
  316. SliderBorderType_t bt = Slider_Idle;
  317. Color col = GetFgColor();
  318. if ( _dragging )
  319. {
  320. col = m_NobDragColor;
  321. bt = Slider_Dragging;
  322. }
  323. else if ( m_bCursorOver && IsMouseOverNob() )
  324. {
  325. col = m_NobFocusColor;
  326. bt = Slider_Hover;
  327. }
  328. surface()->DrawSetColor( col );
  329. IBorder *pBorder = _ScrollBarSliderBorder[ bt ];
  330. int nInset = m_nNobInset;
  331. if (_vertical)
  332. {
  333. // Nob
  334. surface()->DrawFilledRect(nInset, _nobPos[0], wide - nInset, _nobPos[1]);
  335. // border
  336. if (pBorder)
  337. {
  338. pBorder->Paint(nInset, _nobPos[0], wide - nInset, _nobPos[1]);
  339. }
  340. }
  341. else
  342. {
  343. // horizontal nob
  344. surface()->DrawFilledRect(_nobPos[0], nInset, _nobPos[1], tall - nInset );
  345. // border
  346. if (pBorder)
  347. {
  348. pBorder->Paint(_nobPos[0], nInset, _nobPos[1], tall - nInset );
  349. }
  350. }
  351. }
  352. //-----------------------------------------------------------------------------
  353. // Purpose:
  354. //-----------------------------------------------------------------------------
  355. void ScrollBarSlider::PaintBackground()
  356. {
  357. // BaseClass::PaintBackground();
  358. int wide,tall;
  359. GetPaintSize(wide,tall);
  360. surface()->DrawSetColor(GetBgColor());
  361. surface()->DrawFilledRect(0, 0, wide-1, tall-1);
  362. }
  363. //-----------------------------------------------------------------------------
  364. // Purpose: Set the range of the ScrollBarSlider
  365. //-----------------------------------------------------------------------------
  366. void ScrollBarSlider::SetRange(int min,int max)
  367. {
  368. if(max<min)
  369. {
  370. max=min;
  371. }
  372. if(min>max)
  373. {
  374. min=max;
  375. }
  376. _range[0]=min;
  377. _range[1]=max;
  378. // update the value (forces it within the range)
  379. SetValue( _value );
  380. InvalidateLayout();
  381. }
  382. //-----------------------------------------------------------------------------
  383. // Purpose: Get the range values of the ScrollBarSlider
  384. //-----------------------------------------------------------------------------
  385. void ScrollBarSlider::GetRange(int& min,int& max)
  386. {
  387. min=_range[0];
  388. max=_range[1];
  389. }
  390. //-----------------------------------------------------------------------------
  391. // Purpose: Respond to cursor movements, we only care about clicking and dragging
  392. //-----------------------------------------------------------------------------
  393. void ScrollBarSlider::OnCursorMoved(int x,int y)
  394. {
  395. if (!_dragging)
  396. {
  397. return;
  398. }
  399. // input()->GetCursorPos(x, y);
  400. // ScreenToLocal(x, y);
  401. int wide, tall;
  402. GetPaintSize(wide, tall);
  403. tall;
  404. if (_vertical)
  405. {
  406. _nobPos[0] = _nobDragStartPos[0] + (y - _dragStartPos[1]);
  407. _nobPos[1] = _nobDragStartPos[1] + (y - _dragStartPos[1]);
  408. if (_nobPos[1] > tall)
  409. {
  410. _nobPos[0] = tall - (_nobPos[1] - _nobPos[0]);
  411. _nobPos[1] = tall;
  412. SetValue( _range[1] - _rangeWindow );
  413. }
  414. }
  415. else
  416. {
  417. _nobPos[0] = _nobDragStartPos[0] + (x - _dragStartPos[0]);
  418. _nobPos[1] = _nobDragStartPos[1] + (x - _dragStartPos[0]);
  419. if (_nobPos[1] > wide)
  420. {
  421. _nobPos[0] = wide - (_nobPos[1] - _nobPos[0]);
  422. _nobPos[1] = wide;
  423. }
  424. }
  425. if (_nobPos[0] < 0)
  426. {
  427. _nobPos[1] = _nobPos[1] - _nobPos[0];
  428. _nobPos[0] = 0;
  429. SetValue(0);
  430. }
  431. InvalidateLayout(); // not invalidatelayout - because it won't draw while we're scrolling the slider
  432. RecomputeValueFromNobPos();
  433. // Repaint();
  434. SendScrollBarSliderMovedMessage();
  435. }
  436. //-----------------------------------------------------------------------------
  437. // Purpose: Respond to mouse clicks on the ScrollBarSlider
  438. //-----------------------------------------------------------------------------
  439. void ScrollBarSlider::OnMousePressed(MouseCode code)
  440. {
  441. int x,y;
  442. input()->GetCursorPos(x,y);
  443. ScreenToLocal(x,y);
  444. if (_vertical)
  445. {
  446. if ((y >= _nobPos[0]) && (y < _nobPos[1]))
  447. {
  448. _dragging = true;
  449. input()->SetMouseCapture(GetVPanel());
  450. _nobDragStartPos[0] = _nobPos[0];
  451. _nobDragStartPos[1] = _nobPos[1];
  452. _dragStartPos[0] = x;
  453. _dragStartPos[1] = y;
  454. }
  455. else if (y < _nobPos[0])
  456. {
  457. // jump the bar up by the range window
  458. int val = GetValue();
  459. val -= _rangeWindow;
  460. SetValue(val);
  461. }
  462. else if (y >= _nobPos[1])
  463. {
  464. // jump the bar down by the range window
  465. int val = GetValue();
  466. val += _rangeWindow;
  467. SetValue(val);
  468. }
  469. }
  470. else
  471. {
  472. if((x >= _nobPos[0]) && (x < _nobPos[1]))
  473. {
  474. _dragging = true;
  475. input()->SetMouseCapture(GetVPanel());
  476. _nobDragStartPos[0] = _nobPos[0];
  477. _nobDragStartPos[1] = _nobPos[1];
  478. _dragStartPos[0] = x;
  479. _dragStartPos[1] = y;
  480. }
  481. else if (x < _nobPos[0])
  482. {
  483. // jump the bar up by the range window
  484. int val = GetValue();
  485. val -= _rangeWindow;
  486. SetValue(val);
  487. }
  488. else if (x >= _nobPos[1])
  489. {
  490. // jump the bar down by the range window
  491. int val = GetValue();
  492. val += _rangeWindow;
  493. SetValue(val);
  494. }
  495. }
  496. }
  497. //-----------------------------------------------------------------------------
  498. // Purpose: Treat double clicks as single clicks
  499. //-----------------------------------------------------------------------------
  500. void ScrollBarSlider::OnMouseDoublePressed(MouseCode code)
  501. {
  502. OnMousePressed(code);
  503. }
  504. //-----------------------------------------------------------------------------
  505. // Purpose: Stop looking for mouse events when mouse is up.
  506. //-----------------------------------------------------------------------------
  507. void ScrollBarSlider::OnMouseReleased(MouseCode code)
  508. {
  509. if ( !_dragging )
  510. return;
  511. _dragging = false;
  512. input()->SetMouseCapture(0);
  513. SendScrollBarSliderReleasedMessage();
  514. }
  515. //-----------------------------------------------------------------------------
  516. // Purpose: Get the position of the ends of the ScrollBarSlider.
  517. //-----------------------------------------------------------------------------
  518. void ScrollBarSlider::GetNobPos(int& min, int& max)
  519. {
  520. min=_nobPos[0];
  521. max=_nobPos[1];
  522. }
  523. //-----------------------------------------------------------------------------
  524. // Purpose: Set the number of lines visible in the window the ScrollBarSlider is attached to
  525. //-----------------------------------------------------------------------------
  526. void ScrollBarSlider::SetRangeWindow(int rangeWindow)
  527. {
  528. _rangeWindow = rangeWindow;
  529. }
  530. //-----------------------------------------------------------------------------
  531. // Purpose: Get the number of lines visible in the window the ScrollBarSlider is attached to
  532. //-----------------------------------------------------------------------------
  533. int ScrollBarSlider::GetRangeWindow()
  534. {
  535. return _rangeWindow;
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Purpose:
  539. //-----------------------------------------------------------------------------
  540. void ScrollBarSlider::SetButtonOffset(int buttonOffset)
  541. {
  542. _buttonOffset = buttonOffset;
  543. }
  544. void ScrollBarSlider::OnCursorEntered()
  545. {
  546. m_bCursorOver = true;
  547. }
  548. void ScrollBarSlider::OnCursorExited()
  549. {
  550. m_bCursorOver = false;
  551. }
  552. void ScrollBarSlider::SetNobFocusColor( const Color &color )
  553. {
  554. m_NobFocusColor = color;
  555. }
  556. void ScrollBarSlider::SetNobDragColor( const Color &color )
  557. {
  558. m_NobDragColor = color;
  559. }
  560. bool ScrollBarSlider::IsMouseOverNob()
  561. {
  562. int x,y;
  563. input()->GetCursorPos(x,y);
  564. ScreenToLocal(x,y);
  565. int nCheckValue = _vertical ? y : x;
  566. if ( ( nCheckValue >= _nobPos[0] ) &&
  567. ( nCheckValue < _nobPos[1] ) )
  568. {
  569. return true;
  570. }
  571. return false;
  572. }