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.

416 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. // This class is a message box that has two buttons, ok and cancel instead of
  5. // just the ok button of a message box. We use a message box class for the ok button
  6. // and implement another button here.
  7. //=============================================================================//
  8. #include <math.h>
  9. #define PROTECTED_THINGS_DISABLE
  10. #include <vgui/IInput.h>
  11. #include <vgui/ISystem.h>
  12. #include <vgui/ISurface.h>
  13. #include <vgui/IScheme.h>
  14. #include <vgui/IVGui.h>
  15. #include <vgui/IPanel.h>
  16. #include <vgui_controls/Tooltip.h>
  17. #include <vgui_controls/TextEntry.h>
  18. #include <vgui_controls/Controls.h>
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include <tier0/memdbgon.h>
  21. using namespace vgui;
  22. //------------------------------------------------------------------------------------------------------
  23. //------------------------------------------------------------------------------------------------------
  24. static vgui::DHANDLE< TextEntry > s_TooltipWindow;
  25. static int s_iTooltipWindowCount = 0;
  26. //-----------------------------------------------------------------------------
  27. // Purpose: Constructor
  28. //-----------------------------------------------------------------------------
  29. BaseTooltip::BaseTooltip(Panel *parent, const char *text)
  30. {
  31. SetText(text);
  32. _displayOnOneLine = false;
  33. _makeVisible = false;
  34. _isDirty = false;
  35. _enabled = true;
  36. _tooltipDelay = 500; // default delay for opening tooltips
  37. _delay = 0;
  38. }
  39. //-----------------------------------------------------------------------------
  40. // Purpose: Reset the tooltip delay timer
  41. //-----------------------------------------------------------------------------
  42. void BaseTooltip::ResetDelay()
  43. {
  44. _isDirty = true;
  45. _delay = system()->GetTimeMillis() + _tooltipDelay;
  46. }
  47. //-----------------------------------------------------------------------------
  48. // Purpose: Set the tooltip delay before a tooltip comes up.
  49. //-----------------------------------------------------------------------------
  50. void BaseTooltip::SetTooltipDelay( int tooltipDelay )
  51. {
  52. _tooltipDelay = tooltipDelay;
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Purpose: Get the tooltip delay before a tooltip comes up.
  56. //-----------------------------------------------------------------------------
  57. int BaseTooltip::GetTooltipDelay()
  58. {
  59. return _tooltipDelay;
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Purpose: Set the tool tip to display on one line only
  63. // Default is multiple lines.
  64. //-----------------------------------------------------------------------------
  65. void BaseTooltip::SetTooltipFormatToSingleLine()
  66. {
  67. _displayOnOneLine = true;
  68. _isDirty = true;
  69. }
  70. //-----------------------------------------------------------------------------
  71. // Purpose: Set the tool tip to display on multiple lines.
  72. //-----------------------------------------------------------------------------
  73. void BaseTooltip::SetTooltipFormatToMultiLine()
  74. {
  75. _displayOnOneLine = false;
  76. _isDirty = true;
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose: Display the tooltip
  80. //-----------------------------------------------------------------------------
  81. void BaseTooltip::ShowTooltip(Panel *currentPanel)
  82. {
  83. _makeVisible = true;
  84. PerformLayout();
  85. }
  86. void BaseTooltip::SetEnabled( bool bState )
  87. {
  88. _enabled = bState;
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose:
  92. //-----------------------------------------------------------------------------
  93. bool BaseTooltip::ShouldLayout( void )
  94. {
  95. if (!_makeVisible)
  96. return false;
  97. if (_delay > system()->GetTimeMillis())
  98. return false;
  99. // We only need to layout when we first become visible
  100. if ( !_isDirty )
  101. return false;
  102. return true;
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Purpose: Display the tooltip
  106. //-----------------------------------------------------------------------------
  107. void BaseTooltip::HideTooltip()
  108. {
  109. _makeVisible = false;
  110. _isDirty = true;
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Purpose: Set the tooltip text
  114. //-----------------------------------------------------------------------------
  115. void BaseTooltip::SetText(const char *text)
  116. {
  117. _isDirty = true;
  118. if (!text)
  119. {
  120. text = "";
  121. }
  122. if (m_Text.Size() > 0)
  123. {
  124. m_Text.RemoveAll();
  125. }
  126. for (unsigned int i = 0; i < strlen(text); i++)
  127. {
  128. m_Text.AddToTail(text[i]);
  129. }
  130. m_Text.AddToTail('\0');
  131. if (s_TooltipWindow.Get() && m_pParent == s_TooltipWindow.Get()->GetParent())
  132. {
  133. s_TooltipWindow->SetText(m_Text.Base());
  134. }
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose: Get the tooltip text
  138. //-----------------------------------------------------------------------------
  139. const char *BaseTooltip::GetText()
  140. {
  141. return m_Text.Base();
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Purpose: Position the tool tip
  145. //-----------------------------------------------------------------------------
  146. void BaseTooltip::PositionWindow( Panel *pTipPanel )
  147. {
  148. int iTipW, iTipH;
  149. pTipPanel->GetSize( iTipW, iTipH );
  150. int cursorX, cursorY;
  151. input()->GetCursorPos(cursorX, cursorY);
  152. int wide, tall;
  153. surface()->GetScreenSize(wide, tall);
  154. int iParentX = 0, iParentY = 0;
  155. if ( !pTipPanel->IsPopup() )
  156. {
  157. pTipPanel->GetParent()->GetPos( iParentX, iParentY );
  158. pTipPanel->GetParent()->LocalToScreen( iParentX, iParentY );
  159. }
  160. cursorX -= iParentX;
  161. cursorY -= iParentY;
  162. if (wide - iTipW > cursorX)
  163. {
  164. cursorY += 20;
  165. // menu hanging right
  166. if (tall - iTipH > cursorY)
  167. {
  168. // menu hanging down
  169. pTipPanel->SetPos(cursorX, cursorY);
  170. }
  171. else
  172. {
  173. // menu hanging up
  174. pTipPanel->SetPos(cursorX, cursorY - iTipH - 20);
  175. }
  176. }
  177. else
  178. {
  179. // menu hanging left
  180. if (tall - iTipH > cursorY)
  181. {
  182. // menu hanging down
  183. pTipPanel->SetPos(cursorX - iTipW, cursorY);
  184. }
  185. else
  186. {
  187. // menu hanging up
  188. pTipPanel->SetPos(cursorX - iTipW, cursorY - iTipH - 20 );
  189. }
  190. }
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Purpose: Constructor
  194. //-----------------------------------------------------------------------------
  195. TextTooltip::TextTooltip(Panel *parent, const char *text) : BaseTooltip( parent, text )
  196. {
  197. if (!s_TooltipWindow.Get())
  198. {
  199. s_TooltipWindow = new TextEntry(NULL, "tooltip");
  200. s_TooltipWindow->InvalidateLayout(false, true);
  201. // this bit of hackery is necessary because tooltips don't get ApplySchemeSettings called from their parents
  202. IScheme *pScheme = scheme()->GetIScheme( s_TooltipWindow->GetScheme() );
  203. s_TooltipWindow->SetBgColor(s_TooltipWindow->GetSchemeColor("Tooltip.BgColor", s_TooltipWindow->GetBgColor(), pScheme));
  204. s_TooltipWindow->SetFgColor(s_TooltipWindow->GetSchemeColor("Tooltip.TextColor", s_TooltipWindow->GetFgColor(), pScheme));
  205. s_TooltipWindow->SetBorder(pScheme->GetBorder("ToolTipBorder"));
  206. s_TooltipWindow->SetFont( pScheme->GetFont("DefaultSmall", s_TooltipWindow->IsProportional()));
  207. }
  208. s_iTooltipWindowCount++;
  209. // this line prevents the main window from losing focus
  210. // when a tooltip pops up
  211. s_TooltipWindow->MakePopup(false, true);
  212. s_TooltipWindow->SetKeyBoardInputEnabled( false );
  213. s_TooltipWindow->SetMouseInputEnabled( false );
  214. SetText(text);
  215. s_TooltipWindow->SetText(m_Text.Base());
  216. s_TooltipWindow->SetEditable(false);
  217. s_TooltipWindow->SetMultiline(true);
  218. s_TooltipWindow->SetVisible(false);
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose: Destructor
  222. //-----------------------------------------------------------------------------
  223. TextTooltip::~TextTooltip()
  224. {
  225. if (--s_iTooltipWindowCount < 1)
  226. {
  227. if ( s_TooltipWindow.Get() )
  228. {
  229. s_TooltipWindow->MarkForDeletion();
  230. }
  231. s_TooltipWindow = NULL;
  232. }
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Purpose: Set the tooltip text
  236. //-----------------------------------------------------------------------------
  237. void TextTooltip::SetText(const char *text)
  238. {
  239. BaseTooltip::SetText( text );
  240. if (s_TooltipWindow.Get())
  241. {
  242. s_TooltipWindow->SetText(m_Text.Base());
  243. }
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Purpose: gets the font from the scheme
  247. //-----------------------------------------------------------------------------
  248. void TextTooltip::ApplySchemeSettings(IScheme *pScheme)
  249. {
  250. if ( s_TooltipWindow )
  251. {
  252. s_TooltipWindow->SetFont(pScheme->GetFont("DefaultSmall", s_TooltipWindow->IsProportional()));
  253. }
  254. }
  255. //-----------------------------------------------------------------------------
  256. // Purpose: Display the tooltip
  257. //-----------------------------------------------------------------------------
  258. void TextTooltip::ShowTooltip(Panel *currentPanel)
  259. {
  260. if ( s_TooltipWindow.Get() )
  261. {
  262. int nLen = s_TooltipWindow->GetTextLength();
  263. if ( nLen <= 0 )
  264. {
  265. // Empty tool tip, no need to show it
  266. _makeVisible = false;
  267. return;
  268. }
  269. char *pBuf = (char*)_alloca( nLen+1 );
  270. s_TooltipWindow->GetText( pBuf, nLen+1 );
  271. Panel *pCurrentParent = s_TooltipWindow->GetParent();
  272. _isDirty = _isDirty || ( pCurrentParent != currentPanel );
  273. s_TooltipWindow->SetText( m_Text.Base() );
  274. s_TooltipWindow->SetParent(currentPanel);
  275. }
  276. BaseTooltip::ShowTooltip( currentPanel );
  277. }
  278. //-----------------------------------------------------------------------------
  279. // Purpose: Display the tooltip
  280. //-----------------------------------------------------------------------------
  281. void TextTooltip::PerformLayout()
  282. {
  283. if ( !ShouldLayout() )
  284. return;
  285. // we're ready, just make us visible
  286. if ( !s_TooltipWindow.Get() )
  287. return;
  288. _isDirty = false;
  289. s_TooltipWindow->SetVisible(true);
  290. s_TooltipWindow->MakePopup( false, true );
  291. s_TooltipWindow->SetKeyBoardInputEnabled( false );
  292. s_TooltipWindow->SetMouseInputEnabled( false );
  293. // relayout the textwindow immediately so that we know it's size
  294. //m_pTextEntry->InvalidateLayout(true);
  295. SizeTextWindow();
  296. PositionWindow( s_TooltipWindow );
  297. }
  298. //-----------------------------------------------------------------------------
  299. // Purpose: Size the text window so all the text fits inside it.
  300. //-----------------------------------------------------------------------------
  301. void TextTooltip::SizeTextWindow()
  302. {
  303. if ( !s_TooltipWindow.Get() )
  304. return;
  305. if (_displayOnOneLine)
  306. {
  307. // We want the tool tip to be one line
  308. s_TooltipWindow->SetMultiline(false);
  309. s_TooltipWindow->SetToFullWidth();
  310. }
  311. else
  312. {
  313. // We want the tool tip to be one line
  314. s_TooltipWindow->SetMultiline(false);
  315. s_TooltipWindow->SetToFullWidth();
  316. int wide, tall;
  317. s_TooltipWindow->GetSize( wide, tall );
  318. double newWide = sqrt( (2.0/1) * wide * tall );
  319. double newTall = (1/2) * newWide;
  320. s_TooltipWindow->SetMultiline(true);
  321. s_TooltipWindow->SetSize((int)newWide, (int)newTall );
  322. s_TooltipWindow->SetToFullHeight();
  323. s_TooltipWindow->GetSize( wide, tall );
  324. if (( wide < 100 ) && ( s_TooltipWindow->GetNumLines() == 2) )
  325. {
  326. s_TooltipWindow->SetMultiline(false);
  327. s_TooltipWindow->SetToFullWidth();
  328. }
  329. else
  330. {
  331. while ( (float)wide/(float)tall < 2 )
  332. {
  333. s_TooltipWindow->SetSize( wide + 1, tall );
  334. s_TooltipWindow->SetToFullHeight();
  335. s_TooltipWindow->GetSize( wide, tall );
  336. }
  337. }
  338. s_TooltipWindow->GetSize( wide, tall );
  339. // ivgui()->DPrintf("End Ratio: %f\n", (float)wide/(float)tall);
  340. }
  341. }
  342. //-----------------------------------------------------------------------------
  343. // Purpose: Display the tooltip
  344. //-----------------------------------------------------------------------------
  345. void TextTooltip::HideTooltip()
  346. {
  347. if ( s_TooltipWindow.Get() )
  348. {
  349. s_TooltipWindow->SetVisible(false);
  350. }
  351. BaseTooltip::HideTooltip();
  352. }