//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // This class is a message box that has two buttons, ok and cancel instead of // just the ok button of a message box. We use a message box class for the ok button // and implement another button here. //=============================================================================// #include #define PROTECTED_THINGS_DISABLE #include #include #include #include #include #include #include #include #include // memdbgon must be the last include file in a .cpp file!!! #include using namespace vgui; //------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------ static vgui::DHANDLE< TextEntry > s_TooltipWindow; static int s_iTooltipWindowCount = 0; //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- BaseTooltip::BaseTooltip(Panel *parent, const char *text) { SetText(text); _displayOnOneLine = false; _makeVisible = false; _isDirty = false; _enabled = true; _tooltipDelay = 500; // default delay for opening tooltips _delay = 0; } //----------------------------------------------------------------------------- // Purpose: Reset the tooltip delay timer //----------------------------------------------------------------------------- void BaseTooltip::ResetDelay() { _isDirty = true; _delay = system()->GetTimeMillis() + _tooltipDelay; } //----------------------------------------------------------------------------- // Purpose: Set the tooltip delay before a tooltip comes up. //----------------------------------------------------------------------------- void BaseTooltip::SetTooltipDelay( int tooltipDelay ) { _tooltipDelay = tooltipDelay; } //----------------------------------------------------------------------------- // Purpose: Get the tooltip delay before a tooltip comes up. //----------------------------------------------------------------------------- int BaseTooltip::GetTooltipDelay() { return _tooltipDelay; } //----------------------------------------------------------------------------- // Purpose: Set the tool tip to display on one line only // Default is multiple lines. //----------------------------------------------------------------------------- void BaseTooltip::SetTooltipFormatToSingleLine() { _displayOnOneLine = true; _isDirty = true; } //----------------------------------------------------------------------------- // Purpose: Set the tool tip to display on multiple lines. //----------------------------------------------------------------------------- void BaseTooltip::SetTooltipFormatToMultiLine() { _displayOnOneLine = false; _isDirty = true; } //----------------------------------------------------------------------------- // Purpose: Display the tooltip //----------------------------------------------------------------------------- void BaseTooltip::ShowTooltip(Panel *currentPanel) { _makeVisible = true; PerformLayout(); } void BaseTooltip::SetEnabled( bool bState ) { _enabled = bState; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool BaseTooltip::ShouldLayout( void ) { if (!_makeVisible) return false; if (_delay > system()->GetTimeMillis()) return false; // We only need to layout when we first become visible if ( !_isDirty ) return false; return true; } //----------------------------------------------------------------------------- // Purpose: Display the tooltip //----------------------------------------------------------------------------- void BaseTooltip::HideTooltip() { _makeVisible = false; _isDirty = true; } //----------------------------------------------------------------------------- // Purpose: Set the tooltip text //----------------------------------------------------------------------------- void BaseTooltip::SetText(const char *text) { _isDirty = true; if (!text) { text = ""; } if (m_Text.Size() > 0) { m_Text.RemoveAll(); } for (unsigned int i = 0; i < strlen(text); i++) { m_Text.AddToTail(text[i]); } m_Text.AddToTail('\0'); if (s_TooltipWindow.Get() && m_pParent == s_TooltipWindow.Get()->GetParent()) { s_TooltipWindow->SetText(m_Text.Base()); } } //----------------------------------------------------------------------------- // Purpose: Get the tooltip text //----------------------------------------------------------------------------- const char *BaseTooltip::GetText() { return m_Text.Base(); } //----------------------------------------------------------------------------- // Purpose: Position the tool tip //----------------------------------------------------------------------------- void BaseTooltip::PositionWindow( Panel *pTipPanel ) { int iTipW, iTipH; pTipPanel->GetSize( iTipW, iTipH ); int cursorX, cursorY; input()->GetCursorPos(cursorX, cursorY); int wide, tall; surface()->GetScreenSize(wide, tall); int iParentX = 0, iParentY = 0; if ( !pTipPanel->IsPopup() ) { pTipPanel->GetParent()->GetPos( iParentX, iParentY ); pTipPanel->GetParent()->LocalToScreen( iParentX, iParentY ); } cursorX -= iParentX; cursorY -= iParentY; if (wide - iTipW > cursorX) { cursorY += 20; // menu hanging right if (tall - iTipH > cursorY) { // menu hanging down pTipPanel->SetPos(cursorX, cursorY); } else { // menu hanging up pTipPanel->SetPos(cursorX, cursorY - iTipH - 20); } } else { // menu hanging left if (tall - iTipH > cursorY) { // menu hanging down pTipPanel->SetPos(cursorX - iTipW, cursorY); } else { // menu hanging up pTipPanel->SetPos(cursorX - iTipW, cursorY - iTipH - 20 ); } } } //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- TextTooltip::TextTooltip(Panel *parent, const char *text) : BaseTooltip( parent, text ) { if (!s_TooltipWindow.Get()) { s_TooltipWindow = new TextEntry(NULL, "tooltip"); s_TooltipWindow->InvalidateLayout(false, true); // this bit of hackery is necessary because tooltips don't get ApplySchemeSettings called from their parents IScheme *pScheme = scheme()->GetIScheme( s_TooltipWindow->GetScheme() ); s_TooltipWindow->SetBgColor(s_TooltipWindow->GetSchemeColor("Tooltip.BgColor", s_TooltipWindow->GetBgColor(), pScheme)); s_TooltipWindow->SetFgColor(s_TooltipWindow->GetSchemeColor("Tooltip.TextColor", s_TooltipWindow->GetFgColor(), pScheme)); s_TooltipWindow->SetBorder(pScheme->GetBorder("ToolTipBorder")); s_TooltipWindow->SetFont( pScheme->GetFont("DefaultSmall", s_TooltipWindow->IsProportional())); } s_iTooltipWindowCount++; // this line prevents the main window from losing focus // when a tooltip pops up s_TooltipWindow->MakePopup(false, true); s_TooltipWindow->SetKeyBoardInputEnabled( false ); s_TooltipWindow->SetMouseInputEnabled( false ); SetText(text); s_TooltipWindow->SetText(m_Text.Base()); s_TooltipWindow->SetEditable(false); s_TooltipWindow->SetMultiline(true); s_TooltipWindow->SetVisible(false); } //----------------------------------------------------------------------------- // Purpose: Destructor //----------------------------------------------------------------------------- TextTooltip::~TextTooltip() { if (--s_iTooltipWindowCount < 1) { if ( s_TooltipWindow.Get() ) { s_TooltipWindow->MarkForDeletion(); } s_TooltipWindow = NULL; } } //----------------------------------------------------------------------------- // Purpose: Set the tooltip text //----------------------------------------------------------------------------- void TextTooltip::SetText(const char *text) { BaseTooltip::SetText( text ); if (s_TooltipWindow.Get()) { s_TooltipWindow->SetText(m_Text.Base()); } } //----------------------------------------------------------------------------- // Purpose: gets the font from the scheme //----------------------------------------------------------------------------- void TextTooltip::ApplySchemeSettings(IScheme *pScheme) { if ( s_TooltipWindow ) { s_TooltipWindow->SetFont(pScheme->GetFont("DefaultSmall", s_TooltipWindow->IsProportional())); } } //----------------------------------------------------------------------------- // Purpose: Display the tooltip //----------------------------------------------------------------------------- void TextTooltip::ShowTooltip(Panel *currentPanel) { if ( s_TooltipWindow.Get() ) { int nLen = s_TooltipWindow->GetTextLength(); if ( nLen <= 0 ) { // Empty tool tip, no need to show it _makeVisible = false; return; } char *pBuf = (char*)_alloca( nLen+1 ); s_TooltipWindow->GetText( pBuf, nLen+1 ); Panel *pCurrentParent = s_TooltipWindow->GetParent(); _isDirty = _isDirty || ( pCurrentParent != currentPanel ); s_TooltipWindow->SetText( m_Text.Base() ); s_TooltipWindow->SetParent(currentPanel); } BaseTooltip::ShowTooltip( currentPanel ); } //----------------------------------------------------------------------------- // Purpose: Display the tooltip //----------------------------------------------------------------------------- void TextTooltip::PerformLayout() { if ( !ShouldLayout() ) return; // we're ready, just make us visible if ( !s_TooltipWindow.Get() ) return; _isDirty = false; s_TooltipWindow->SetVisible(true); s_TooltipWindow->MakePopup( false, true ); s_TooltipWindow->SetKeyBoardInputEnabled( false ); s_TooltipWindow->SetMouseInputEnabled( false ); // relayout the textwindow immediately so that we know it's size //m_pTextEntry->InvalidateLayout(true); SizeTextWindow(); PositionWindow( s_TooltipWindow ); } //----------------------------------------------------------------------------- // Purpose: Size the text window so all the text fits inside it. //----------------------------------------------------------------------------- void TextTooltip::SizeTextWindow() { if ( !s_TooltipWindow.Get() ) return; if (_displayOnOneLine) { // We want the tool tip to be one line s_TooltipWindow->SetMultiline(false); s_TooltipWindow->SetToFullWidth(); } else { // We want the tool tip to be one line s_TooltipWindow->SetMultiline(false); s_TooltipWindow->SetToFullWidth(); int wide, tall; s_TooltipWindow->GetSize( wide, tall ); double newWide = sqrt( (2.0/1) * wide * tall ); double newTall = (1/2) * newWide; s_TooltipWindow->SetMultiline(true); s_TooltipWindow->SetSize((int)newWide, (int)newTall ); s_TooltipWindow->SetToFullHeight(); s_TooltipWindow->GetSize( wide, tall ); if (( wide < 100 ) && ( s_TooltipWindow->GetNumLines() == 2) ) { s_TooltipWindow->SetMultiline(false); s_TooltipWindow->SetToFullWidth(); } else { while ( (float)wide/(float)tall < 2 ) { s_TooltipWindow->SetSize( wide + 1, tall ); s_TooltipWindow->SetToFullHeight(); s_TooltipWindow->GetSize( wide, tall ); } } s_TooltipWindow->GetSize( wide, tall ); // ivgui()->DPrintf("End Ratio: %f\n", (float)wide/(float)tall); } } //----------------------------------------------------------------------------- // Purpose: Display the tooltip //----------------------------------------------------------------------------- void TextTooltip::HideTooltip() { if ( s_TooltipWindow.Get() ) { s_TooltipWindow->SetVisible(false); } BaseTooltip::HideTooltip(); }