From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/vgui2/vgui_controls/Label.cpp | 2772 +++++++++++++++++----------------- 1 file changed, 1386 insertions(+), 1386 deletions(-) (limited to 'mp/src/vgui2/vgui_controls/Label.cpp') diff --git a/mp/src/vgui2/vgui_controls/Label.cpp b/mp/src/vgui2/vgui_controls/Label.cpp index 26199308..776c8c6e 100644 --- a/mp/src/vgui2/vgui_controls/Label.cpp +++ b/mp/src/vgui2/vgui_controls/Label.cpp @@ -1,1386 +1,1386 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -// memdbgon must be the last include file in a .cpp file!!! -#include - -using namespace vgui; - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -DECLARE_BUILD_FACTORY_DEFAULT_TEXT( Label, Label ); - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -Label::Label(Panel *parent, const char *panelName, const char *text) : BaseClass(parent, panelName) -{ - Init(); - - _textImage = new TextImage(text); - _textImage->SetColor(Color(0, 0, 0, 0)); - SetText(text); - _textImageIndex = AddImage(_textImage, 0); - - REGISTER_COLOR_AS_OVERRIDABLE( _disabledFgColor2, "disabledfgcolor2_override" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -Label::Label(Panel *parent, const char *panelName, const wchar_t *wszText) : BaseClass(parent, panelName) -{ - Init(); - - _textImage = new TextImage(wszText); - _textImage->SetColor(Color(0, 0, 0, 0)); - SetText(wszText); - _textImageIndex = AddImage(_textImage, 0); - - REGISTER_COLOR_AS_OVERRIDABLE( _disabledFgColor2, "disabledfgcolor2_override" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -//----------------------------------------------------------------------------- -Label::~Label() -{ - delete _textImage; - delete [] _associateName; - delete [] _fontOverrideName; -} - -//----------------------------------------------------------------------------- -// Purpose: Construct the label -//----------------------------------------------------------------------------- -void Label::Init() -{ - _contentAlignment = a_west; - _textColorState = CS_NORMAL; - _textInset[0] = 0; - _textInset[1] = 0; - _hotkey = 0; - _associate = NULL; - _associateName = NULL; - _fontOverrideName = NULL; - m_bWrap = false; - m_bCenterWrap = false; - m_bAutoWideToContents = false; - m_bUseProportionalInsets = false; - m_bAutoWideDirty = false; - -// SetPaintBackgroundEnabled(false); -} - -//----------------------------------------------------------------------------- -// Purpose: Set whether the text is displayed bright or dull -//----------------------------------------------------------------------------- -void Label::SetTextColorState(EColorState state) -{ - if (_textColorState != state) - { - _textColorState = state; - InvalidateLayout(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return the full size of the contained content -//----------------------------------------------------------------------------- -void Label::GetContentSize(int &wide, int &tall) -{ - if( GetFont() == INVALID_FONT ) // we haven't loaded our font yet, so load it now - { - IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); - if ( pScheme ) - { - SetFont( pScheme->GetFont( "Default", IsProportional() ) ); - } - } - - - int tx0, ty0, tx1, ty1; - ComputeAlignment(tx0, ty0, tx1, ty1); - - // the +8 is padding to the content size - // the code which uses it should really set that itself; - // however a lot of existing code relies on this - wide = (tx1 - tx0) + _textInset[0]; - - // get the size of the text image and remove it - int iWide, iTall; - _textImage->GetSize(iWide, iTall); - wide -= iWide; - // get the full, untruncated (no elipsis) size of the text image. - _textImage->GetContentSize(iWide, iTall); - wide += iWide; - - // addin the image offsets as well - for (int i=0; i < _imageDar.Size(); i++) - wide += _imageDar[i].offset; - - tall = max((ty1 - ty0) + _textInset[1], iTall); -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate the keyboard key that is a hotkey -//----------------------------------------------------------------------------- -wchar_t Label::CalculateHotkey(const char *text) -{ - for (const char *ch = text; *ch != 0; ch++) - { - if (*ch == '&') - { - // get the next character - ch++; - - if (*ch == '&') - { - // just an & - continue; - } - else if (*ch == 0) - { - break; - } - else if (V_isalnum(*ch)) - { - // found the hotkey - return (wchar_t)tolower(*ch); - } - } - } - - return '\0'; -} - -wchar_t Label::CalculateHotkey(const wchar_t *text) -{ - if( text ) - { - for (const wchar_t *ch = text; *ch != 0; ch++) - { - if (*ch == '&') - { - // get the next character - ch++; - - if (*ch == '&') - { - // just an & - continue; - } - else if (*ch == 0) - { - break; - } - else if (iswalnum(*ch)) - { - // found the hotkey - return (wchar_t)towlower(*ch); - } - } - } - } - - return '\0'; -} - -//----------------------------------------------------------------------------- -// Purpose: Check if this label has a hotkey that is the key passed in. -//----------------------------------------------------------------------------- -Panel *Label::HasHotkey(wchar_t key) -{ -#ifdef VGUI_HOTKEYS_ENABLED - if ( iswalnum( key ) ) - key = towlower( key ); - - if (_hotkey == key) - return this; -#endif - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Set the hotkey for this label -//----------------------------------------------------------------------------- -void Label::SetHotkey(wchar_t ch) -{ - _hotkey = ch; -} - -wchar_t Label::GetHotKey() -{ - return _hotkey; -} - -//----------------------------------------------------------------------------- -// Purpose: Handle a hotkey by passing on focus to associate -//----------------------------------------------------------------------------- -void Label::OnHotkeyPressed() -{ - // we can't accept focus, but if we are associated to a control give it to that - if (_associate.Get() && !IsBuildModeActive()) - { - _associate->RequestFocus(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Redirect mouse pressed to giving focus to associate -//----------------------------------------------------------------------------- -void Label::OnMousePressed(MouseCode code) -{ - if (_associate.Get() && !IsBuildModeActive()) - { - _associate->RequestFocus(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return the text in the label -//----------------------------------------------------------------------------- -void Label::GetText(char *textOut, int bufferLen) -{ - _textImage->GetText(textOut, bufferLen); -} - -//----------------------------------------------------------------------------- -// Purpose: Return the text in the label -//----------------------------------------------------------------------------- -void Label::GetText(wchar_t *textOut, int bufLenInBytes) -{ - _textImage->GetText(textOut, bufLenInBytes); -} - -//----------------------------------------------------------------------------- -// Purpose: Take the string and looks it up in the localization file -// to convert it to unicode -// Setting the text will not set the size of the label. -// Set the size explicitly or use setToContent() -//----------------------------------------------------------------------------- -void Label::SetText(const char *text) -{ - // if set to null, just make blank - if (!text) - { - text = ""; - } - - // let the text image do the translation itself - _textImage->SetText(text); - - if( text[0] == '#' ) - { - SetHotkey(CalculateHotkey(g_pVGuiLocalize->Find(text))); - } - else - { - SetHotkey(CalculateHotkey(text)); - } - - m_bAutoWideDirty = m_bAutoWideToContents; - - InvalidateLayout(); - Repaint(); -} - -//----------------------------------------------------------------------------- -// Purpose: Set unicode text directly -//----------------------------------------------------------------------------- -void Label::SetText(const wchar_t *unicodeString, bool bClearUnlocalizedSymbol) -{ - m_bAutoWideDirty = m_bAutoWideToContents; - - if ( unicodeString && _textImage->GetUText() && !Q_wcscmp(unicodeString,_textImage->GetUText()) ) - return; - - _textImage->SetText(unicodeString, bClearUnlocalizedSymbol); - -//!! need to calculate hotkey from translated string - SetHotkey(CalculateHotkey(unicodeString)); - - InvalidateLayout(); // possible that the textimage needs to expand - Repaint(); -} - -//----------------------------------------------------------------------------- -// Purpose: updates localized text -//----------------------------------------------------------------------------- -void Label::OnDialogVariablesChanged(KeyValues *dialogVariables ) -{ - StringIndex_t index = _textImage->GetUnlocalizedTextSymbol(); - if (index != INVALID_LOCALIZE_STRING_INDEX) - { - // reconstruct the string from the variables - wchar_t buf[1024]; - g_pVGuiLocalize->ConstructString(buf, sizeof(buf), index, dialogVariables); - SetText(buf); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Additional offset at the Start of the text (from whichever side it is aligned) -//----------------------------------------------------------------------------- -void Label::SetTextInset(int xInset, int yInset) -{ - _textInset[0] = xInset; - _textInset[1] = yInset; - - int wide, tall; - GetSize( wide, tall); - _textImage->SetDrawWidth(wide - _textInset[0]); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Label::GetTextInset(int *xInset, int *yInset ) -{ - *xInset = _textInset[0]; - *yInset = _textInset[1]; -} - -//----------------------------------------------------------------------------- -// Purpose: Set the enabled state -//----------------------------------------------------------------------------- -void Label::SetEnabled(bool state) -{ - Panel::SetEnabled(state); -} - -//----------------------------------------------------------------------------- -// Purpose: Calculates where in the panel the content resides -// Input : &tx0 - [out] position of the content -// &ty0 - -// &tx1 - -// &ty1 - -// Note: horizontal alignment is west if the image dar has -// more than one image in it, this is because we use image sizes -// to determine layout in classes for example, Menu. -//----------------------------------------------------------------------------- -void Label::ComputeAlignment(int &tx0, int &ty0, int &tx1, int &ty1) -{ - int wide, tall; - GetPaintSize(wide, tall); - int tWide,tTall; - - // text bounding box - tx0 = 0; - ty0 = 0; - - // loop through all the images and calculate the complete bounds - int maxX = 0, maxY = 0; - - int actualXAlignment = _contentAlignment; - for (int i = 0; i < _imageDar.Count(); i++) - { - TImageInfo &imageInfo = _imageDar[i]; - IImage *image = imageInfo.image; - if (!image) - continue; // skip over null images - - // add up the bounds - int iWide, iTall; - image->GetSize(iWide, iTall); - if (iWide > wide) // if the image is larger than the label just do a west alignment - actualXAlignment = Label::a_west; - - // get the max height - maxY = max(maxY, iTall); - maxX += iWide; - - // add the offset to x - maxX += imageInfo.offset; - } - - tWide = maxX; - tTall = maxY; - - // x align text - switch (actualXAlignment) - { - // left - case Label::a_northwest: - case Label::a_west: - case Label::a_southwest: - { - tx0 = 0; - break; - } - // center - case Label::a_north: - case Label::a_center: - case Label::a_south: - { - tx0 = (wide - tWide) / 2; - break; - } - // right - case Label::a_northeast: - case Label::a_east: - case Label::a_southeast: - { - tx0 = wide - tWide; - break; - } - } - - // y align text - switch (_contentAlignment) - { - //top - case Label::a_northwest: - case Label::a_north: - case Label::a_northeast: - { - ty0 = 0; - break; - } - // center - case Label::a_west: - case Label::a_center: - case Label::a_east: - { - ty0 = (tall - tTall) / 2; - break; - } - // south - case Label::a_southwest: - case Label::a_south: - case Label::a_southeast: - { - ty0 = tall - tTall; - break; - } - } - - tx1 = tx0 + tWide; - ty1 = ty0 + tTall; -} - -//----------------------------------------------------------------------------- -// Purpose: overridden main drawing function for the panel -//----------------------------------------------------------------------------- -void Label::Paint() -{ - int tx0, ty0, tx1, ty1; - ComputeAlignment(tx0, ty0, tx1, ty1); - - // calculate who our associate is if we haven't already - if (_associateName) - { - SetAssociatedControl(FindSiblingByName(_associateName)); - delete [] _associateName; - _associateName = NULL; - } - - int labelWide, labelTall; - GetSize(labelWide, labelTall); - int x = tx0, y = _textInset[1] + ty0; - int imageYPos = 0; // a place to save the y offset for when we draw the disable version of the image - - // draw the set of images - for (int i = 0; i < _imageDar.Count(); i++) - { - TImageInfo &imageInfo = _imageDar[i]; - IImage *image = imageInfo.image; - if (!image) - continue; // skip over null images - - // add the offset to x - x += imageInfo.offset; - - // if this is the text image then add its inset to the left or from the right - if (i == _textImageIndex) - { - switch ( _contentAlignment ) - { - // left - case Label::a_northwest: - case Label::a_west: - case Label::a_southwest: - { - x += _textInset[0]; - break; - } - // right - case Label::a_northeast: - case Label::a_east: - case Label::a_southeast: - { - x -= _textInset[0]; - break; - } - } - } - - // see if the image is in a fixed position - if (imageInfo.xpos >= 0) - { - x = imageInfo.xpos; - } - - // draw - imageYPos = y; - image->SetPos(x, y); - - // fix up y for center-aligned text - if (_contentAlignment == Label::a_west || _contentAlignment == Label::a_center || _contentAlignment == Label::a_east) - { - int iw, it; - image->GetSize(iw, it); - if (it < (ty1 - ty0)) - { - imageYPos = ((ty1 - ty0) - it) / 2 + y; - image->SetPos(x, ((ty1 - ty0) - it) / 2 + y); - } - } - - // don't resize the image unless its too big - if (imageInfo.width >= 0) - { - int w, t; - image->GetSize(w, t); - if (w > imageInfo.width) - { - image->SetSize(imageInfo.width, t); - } - } - - // if it's the basic text image then draw specially - if (image == _textImage) - { - if (IsEnabled()) - { - if (_associate.Get() && ipanel()->HasParent(input()->GetFocus(), _associate->GetVPanel())) - { - _textImage->SetColor(_associateColor); - } - else - { - _textImage->SetColor(GetFgColor()); - } - - _textImage->Paint(); - } - else - { - // draw disabled version, with embossed look - // offset image - _textImage->SetPos(x + 1, imageYPos + 1); - _textImage->SetColor(_disabledFgColor1); - _textImage->Paint(); - - surface()->DrawFlushText(); - - // overlayed image - _textImage->SetPos(x, imageYPos); - _textImage->SetColor(_disabledFgColor2); - _textImage->Paint(); - } - } - else - { - image->Paint(); - } - - // add the image size to x - int wide, tall; - image->GetSize(wide, tall); - x += wide; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Helper function, draws a simple line with dashing parameters -//----------------------------------------------------------------------------- -void Label::DrawDashedLine(int x0, int y0, int x1, int y1, int dashLen, int gapLen) -{ - // work out which way the line goes - if ((x1 - x0) > (y1 - y0)) - { - // x direction line - while (1) - { - if (x0 + dashLen > x1) - { - // draw partial - surface()->DrawFilledRect(x0, y0, x1, y1); - } - else - { - surface()->DrawFilledRect(x0, y0, x0 + dashLen, y1); - } - - x0 += dashLen; - - if (x0 + gapLen > x1) - break; - - x0 += gapLen; - } - } - else - { - // y direction - while (1) - { - if (y0 + dashLen > y1) - { - // draw partial - surface()->DrawFilledRect(x0, y0, x1, y1); - } - else - { - surface()->DrawFilledRect(x0, y0, x1, y0 + dashLen); - } - - y0 += dashLen; - - if (y0 + gapLen > y1) - break; - - y0 += gapLen; - } - } -} - -void Label::SetContentAlignment(Alignment alignment) -{ - _contentAlignment=alignment; - Repaint(); -} - -//----------------------------------------------------------------------------- -// Purpose: Size the width of the label to its contents - only works from in ApplySchemeSettings or PerformLayout() -//----------------------------------------------------------------------------- -void Label::SizeToContents() -{ - int wide, tall; - GetContentSize(wide, tall); - - SetSize(wide, tall); -} - -//----------------------------------------------------------------------------- -// Purpose: Set the font the text is drawn in -//----------------------------------------------------------------------------- -void Label::SetFont(HFont font) -{ - _textImage->SetFont(font); - Repaint(); -} - -//----------------------------------------------------------------------------- -// Purpose: Resond to resizing of the panel -//----------------------------------------------------------------------------- -void Label::OnSizeChanged(int wide, int tall) -{ - InvalidateLayout(); - Panel::OnSizeChanged(wide, tall); -} - -//----------------------------------------------------------------------------- -// Purpose: Get the font the textImage is drawn in. -//----------------------------------------------------------------------------- -HFont Label::GetFont() -{ - return _textImage->GetFont(); -} - -//----------------------------------------------------------------------------- -// Purpose: Set the foreground color of the Label -//----------------------------------------------------------------------------- -void Label::SetFgColor(Color color) -{ - if (!(GetFgColor() == color)) - { - BaseClass::SetFgColor(color); - _textImage->SetColor(color); - Repaint(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get the foreground color of the Label -//----------------------------------------------------------------------------- -Color Label::GetFgColor() -{ - Color clr = Panel::GetFgColor(); - return clr; -} - -//----------------------------------------------------------------------------- -// Purpose: Set the foreground color 1 color of the Label -//----------------------------------------------------------------------------- -void Label::SetDisabledFgColor1(Color color) -{ - _disabledFgColor1 = color; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Label::SetDisabledFgColor2(Color color) -{ - _disabledFgColor2 = color; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Color Label::GetDisabledFgColor1() -{ - return _disabledFgColor1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Color Label::GetDisabledFgColor2() -{ - return _disabledFgColor2; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -TextImage *Label::GetTextImage() -{ - return _textImage; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool Label::RequestInfo(KeyValues *outputData) -{ - if (!stricmp(outputData->GetName(), "GetText")) - { - wchar_t wbuf[256]; - _textImage->GetText(wbuf, 255); - outputData->SetWString("text", wbuf); - return true; - } - - return Panel::RequestInfo(outputData); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the text from the message -//----------------------------------------------------------------------------- -void Label::OnSetText(KeyValues *params) -{ - KeyValues *pkvText = params->FindKey("text", false); - if (!pkvText) - return; - - if (pkvText->GetDataType() == KeyValues::TYPE_STRING) - { - SetText(pkvText->GetString()); - } - else if (pkvText->GetDataType() == KeyValues::TYPE_WSTRING) - { - SetText(pkvText->GetWString()); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Add an image to the list -// returns the index the image was placed in -//----------------------------------------------------------------------------- -int Label::AddImage(IImage *image, int offset) -{ - int newImage = _imageDar.AddToTail(); - _imageDar[newImage].image = image; - _imageDar[newImage].offset = (short)offset; - _imageDar[newImage].xpos = -1; - _imageDar[newImage].width = -1; - InvalidateLayout(); - return newImage; -} - -//----------------------------------------------------------------------------- -// Purpose: removes all images from the list -// user is responsible for the memory -//----------------------------------------------------------------------------- -void Label::ClearImages() -{ - _imageDar.RemoveAll(); - _textImageIndex = -1; -} - -void Label::ResetToSimpleTextImage() -{ - ClearImages(); - _textImageIndex = AddImage(_textImage, 0); -} - - -//----------------------------------------------------------------------------- -// Purpose: Multiple image handling -// Images are drawn from left to right across the label, ordered by index -// By default there is a TextImage in position 0 -// Set the contents of an IImage in the IImage array. -//----------------------------------------------------------------------------- -void Label::SetImageAtIndex(int index, IImage *image, int offset) -{ - EnsureImageCapacity(index); -// Assert( image ); - - if ( _imageDar[index].image != image || _imageDar[index].offset != offset) - { - _imageDar[index].image = image; - _imageDar[index].offset = (short)offset; - InvalidateLayout(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get an IImage in the IImage array. -//----------------------------------------------------------------------------- -IImage *Label::GetImageAtIndex(int index) -{ - if ( _imageDar.IsValidIndex( index ) ) - return _imageDar[index].image; - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the number of images in the array. -//----------------------------------------------------------------------------- -int Label::GetImageCount() -{ - return _imageDar.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: Move where the default text image is within the image array -// (it starts in position 0) -// Input : newIndex - -// Output : int - the index the default text image was previously in -//----------------------------------------------------------------------------- -int Label::SetTextImageIndex(int newIndex) -{ - if (newIndex == _textImageIndex) - return _textImageIndex; - - EnsureImageCapacity(newIndex); - - int oldIndex = _textImageIndex; - if ( _textImageIndex >= 0 ) - { - _imageDar[_textImageIndex].image = NULL; - } - if (newIndex > -1) - { - _imageDar[newIndex].image = _textImage; - } - _textImageIndex = newIndex; - return oldIndex; -} - -//----------------------------------------------------------------------------- -// Purpose: Ensure that the maxIndex will be a valid index -//----------------------------------------------------------------------------- -void Label::EnsureImageCapacity(int maxIndex) -{ - while (_imageDar.Size() <= maxIndex) - { - AddImage(NULL, 0); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Set the offset in pixels before the image -//----------------------------------------------------------------------------- -void Label::SetImagePreOffset(int index, int preOffset) -{ - if (_imageDar.IsValidIndex(index) && _imageDar[index].offset != preOffset) - { - _imageDar[index].offset = (short)preOffset; - InvalidateLayout(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: fixes the layout bounds of the image within the label -//----------------------------------------------------------------------------- -void Label::SetImageBounds(int index, int x, int width) -{ - _imageDar[index].xpos = (short)x; - _imageDar[index].width = (short)width; -} - -//----------------------------------------------------------------------------- -// Purpose: Labels can be associated with controls, and alter behaviour based on the associates behaviour -// If the associate is disabled, so are we -// If the associate has focus, we may alter how we draw -// If we get a hotkey press or focus message, we forward the focus to the associate -//----------------------------------------------------------------------------- -void Label::SetAssociatedControl(Panel *control) -{ - if (control != this) - { - _associate = control; - } - else - { - // don't let the associate ever be set to be ourself - _associate = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called after a panel requests focus to fix up the whole chain -//----------------------------------------------------------------------------- -void Label::OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel) -{ - if (_associate.Get() && subFocus == GetVPanel() && !IsBuildModeActive()) - { - // we've received focus; pass the focus onto the associate instead - _associate->RequestFocus(); - } - else - { - BaseClass::OnRequestFocus(subFocus, defaultPanel); - } -} - -//----------------------------------------------------------------------------- -// Purpose: sets custom settings from the scheme file -//----------------------------------------------------------------------------- -void Label::ApplySchemeSettings(IScheme *pScheme) -{ - BaseClass::ApplySchemeSettings(pScheme); - - if (_fontOverrideName) - { - // use the custom specified font since we have one set - SetFont(pScheme->GetFont(_fontOverrideName, IsProportional())); - } - if ( GetFont() == INVALID_FONT ) - { - SetFont( pScheme->GetFont( "Default", IsProportional() ) ); - } - - if ( m_bWrap || m_bCenterWrap ) - { - //tell it how big it is - int wide, tall; - Panel::GetSize(wide, tall); - wide -= _textInset[0]; // take inset into account - _textImage->SetSize(wide, tall); - - _textImage->RecalculateNewLinePositions(); - } - else - { - // if you don't set the size of the image, many, many buttons will break - we might want to look into fixing this all over the place later - int wide, tall; - _textImage->GetContentSize(wide, tall); - _textImage->SetSize(wide, tall); - } - - if ( m_bAutoWideToContents ) - { - m_bAutoWideDirty = true; - HandleAutoSizing(); - } - - // clear out any the images, since they will have been invalidated - for (int i = 0; i < _imageDar.Count(); i++) - { - IImage *image = _imageDar[i].image; - if (!image) - continue; // skip over null images - - if (i == _textImageIndex) - continue; - - _imageDar[i].image = NULL; - } - - SetDisabledFgColor1(GetSchemeColor("Label.DisabledFgColor1", pScheme)); - SetDisabledFgColor2(GetSchemeColor("Label.DisabledFgColor2", pScheme)); - SetBgColor(GetSchemeColor("Label.BgColor", pScheme)); - - switch (_textColorState) - { - case CS_DULL: - SetFgColor(GetSchemeColor("Label.TextDullColor", pScheme)); - break; - case CS_BRIGHT: - SetFgColor(GetSchemeColor("Label.TextBrightColor", pScheme)); - break; - case CS_NORMAL: - default: - SetFgColor(GetSchemeColor("Label.TextColor", pScheme)); - break; - } - - _associateColor = GetSchemeColor("Label.SelectedTextColor", pScheme); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Label::GetSettings( KeyValues *outResourceData ) -{ - // panel settings - Panel::GetSettings( outResourceData ); - - // label settings - char buf[256]; - _textImage->GetUnlocalizedText( buf, 255 ); - if (!strnicmp(buf, "#var_", 5)) - { - // strip off the variable prepender on save - outResourceData->SetString( "labelText", buf + 5 ); - } - else - { - outResourceData->SetString( "labelText", buf ); - } - - const char *alignmentString = ""; - switch ( _contentAlignment ) - { - case a_northwest: alignmentString = "north-west"; break; - case a_north: alignmentString = "north"; break; - case a_northeast: alignmentString = "north-east"; break; - case a_center: alignmentString = "center"; break; - case a_east: alignmentString = "east"; break; - case a_southwest: alignmentString = "south-west"; break; - case a_south: alignmentString = "south"; break; - case a_southeast: alignmentString = "south-east"; break; - case a_west: - default: alignmentString = "west"; break; - } - - outResourceData->SetString( "textAlignment", alignmentString ); - - if (_associate) - { - outResourceData->SetString("associate", _associate->GetName()); - } - - outResourceData->SetInt("dulltext", (int)(_textColorState == CS_DULL)); - outResourceData->SetInt("brighttext", (int)(_textColorState == CS_BRIGHT)); - - if (_fontOverrideName) - { - outResourceData->SetString("font", _fontOverrideName); - } - - outResourceData->SetInt("wrap", ( m_bWrap ? 1 : 0 )); - outResourceData->SetInt("centerwrap", ( m_bCenterWrap ? 1 : 0 )); - - if ( m_bUseProportionalInsets ) - { - outResourceData->SetInt("textinsetx", scheme()->GetProportionalNormalizedValueEx( GetScheme(), _textInset[0] ) ); - outResourceData->SetInt("textinsety", _textInset[1]); - } - else - { - outResourceData->SetInt("textinsetx", _textInset[0]); - outResourceData->SetInt("textinsety", _textInset[1]); - } - outResourceData->SetInt("auto_wide_tocontents", ( m_bAutoWideToContents ? 1 : 0 )); - outResourceData->SetInt("use_proportional_insets", ( m_bUseProportionalInsets ? 1 : 0 )); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Label::ApplySettings( KeyValues *inResourceData ) -{ - BaseClass::ApplySettings( inResourceData ); - - // label settings - const char *labelText = inResourceData->GetString( "labelText", NULL ); - if ( labelText ) - { - if (labelText[0] == '%' && labelText[strlen(labelText) - 1] == '%') - { - // it's a variable, set it to be a special variable localized string - wchar_t unicodeVar[256]; - g_pVGuiLocalize->ConvertANSIToUnicode(labelText, unicodeVar, sizeof(unicodeVar)); - - char var[256]; - _snprintf(var, sizeof(var), "#var_%s", labelText); - g_pVGuiLocalize->AddString(var + 1, unicodeVar, ""); - SetText(var); - } - else - { - SetText(labelText); - } - } - - // text alignment - const char *alignmentString = inResourceData->GetString( "textAlignment", "" ); - int align = -1; - - if ( !stricmp(alignmentString, "north-west") ) - { - align = a_northwest; - } - else if ( !stricmp(alignmentString, "north") ) - { - align = a_north; - } - else if ( !stricmp(alignmentString, "north-east") ) - { - align = a_northeast; - } - else if ( !stricmp(alignmentString, "west") ) - { - align = a_west; - } - else if ( !stricmp(alignmentString, "center") ) - { - align = a_center; - } - else if ( !stricmp(alignmentString, "east") ) - { - align = a_east; - } - else if ( !stricmp(alignmentString, "south-west") ) - { - align = a_southwest; - } - else if ( !stricmp(alignmentString, "south") ) - { - align = a_south; - } - else if ( !stricmp(alignmentString, "south-east") ) - { - align = a_southeast; - } - - if ( align != -1 ) - { - SetContentAlignment( (Alignment)align ); - } - - // the control we are to be associated with may not have been created yet, - // so keep a pointer to it's name and calculate it when we can - const char *associateName = inResourceData->GetString("associate", ""); - if (associateName[0] != 0) - { - int len = Q_strlen(associateName) + 1; - _associateName = new char[ len ]; - Q_strncpy( _associateName, associateName, len ); - } - - if (inResourceData->GetInt("dulltext", 0) == 1) - { - SetTextColorState(CS_DULL); - } - else if (inResourceData->GetInt("brighttext", 0) == 1) - { - SetTextColorState(CS_BRIGHT); - } - else - { - SetTextColorState(CS_NORMAL); - } - - // font settings - const char *overrideFont = inResourceData->GetString("font", ""); - IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); - - if (*overrideFont) - { - delete [] _fontOverrideName; - int len = Q_strlen(overrideFont) + 1; - _fontOverrideName = new char[ len ]; - Q_strncpy(_fontOverrideName, overrideFont, len ); - SetFont(pScheme->GetFont(_fontOverrideName, IsProportional())); - } - else if (_fontOverrideName) - { - delete [] _fontOverrideName; - _fontOverrideName = NULL; - SetFont(pScheme->GetFont("Default", IsProportional())); - } - - bool bWrapText = inResourceData->GetInt("centerwrap", 0) > 0; - SetCenterWrap( bWrapText ); - - m_bAutoWideToContents = inResourceData->GetInt("auto_wide_tocontents", 0) > 0; - - bWrapText = inResourceData->GetInt("wrap", 0) > 0; - SetWrap( bWrapText ); - - int inset_x = inResourceData->GetInt("textinsetx", _textInset[0]); - int inset_y = inResourceData->GetInt("textinsety", _textInset[1]); - // Had to play it safe and add a new key for backwards compatibility - m_bUseProportionalInsets = inResourceData->GetInt("use_proportional_insets", 0) > 0; - if ( m_bUseProportionalInsets ) - { - inset_x = scheme()->GetProportionalScaledValueEx( GetScheme(), inset_x ); - } - - SetTextInset( inset_x, inset_y ); - - bool bAllCaps = inResourceData->GetInt("allcaps", 0) > 0; - SetAllCaps( bAllCaps ); - - InvalidateLayout(true); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a description of the label string -//----------------------------------------------------------------------------- -const char *Label::GetDescription( void ) -{ - static char buf[1024]; - Q_snprintf(buf, sizeof(buf), "%s, string labelText, string associate, alignment textAlignment, int wrap, int dulltext, int brighttext, string font", BaseClass::GetDescription()); - return buf; -} - -//----------------------------------------------------------------------------- -// Purpose: If a label has images in _imageDar, the size -// must take those into account as well as the textImage part -// Textimage part will shrink ONLY if there is not enough room. -//----------------------------------------------------------------------------- -void Label::PerformLayout() -{ - int wide, tall; - Panel::GetSize(wide, tall); - wide -= _textInset[0]; // take inset into account - - // if we just have a textImage, this is trivial. - if (_imageDar.Count() == 1 && _textImageIndex == 0) - { - if ( m_bWrap || m_bCenterWrap ) - { - int twide, ttall; - _textImage->GetContentSize(twide, ttall); - _textImage->SetSize(wide, ttall); - } - else - { - int twide, ttall; - _textImage->GetContentSize(twide, ttall); - - // tell the textImage how much space we have to draw in - if ( wide < twide) - _textImage->SetSize(wide, ttall); - else - _textImage->SetSize(twide, ttall); - } - - HandleAutoSizing(); - - HandleAutoSizing(); - - return; - } - - // assume the images in the dar cannot be resized, and if - // the images + the textimage are too wide we shring the textimage part - if (_textImageIndex < 0) - return; - - // get the size of the images - int widthOfImages = 0; - for (int i = 0; i < _imageDar.Count(); i++) - { - TImageInfo &imageInfo = _imageDar[i]; - IImage *image = imageInfo.image; - if (!image) - continue; // skip over null images - - if (i == _textImageIndex) - continue; - - // add up the bounds - int iWide, iTall; - image->GetSize(iWide, iTall); - widthOfImages += iWide; - } - - // so this is how much room we have to draw the textimage part - int spaceAvail = wide - widthOfImages; - - // if we have no space at all just leave everything as is. - if (spaceAvail < 0) - return; - - int twide, ttall; - _textImage->GetSize (twide, ttall); - // tell the textImage how much space we have to draw in - _textImage->SetSize(spaceAvail, ttall); - - HandleAutoSizing(); -} - -void Label::SetWrap( bool bWrap ) -{ - m_bWrap = bWrap; - _textImage->SetWrap( m_bWrap ); - - InvalidateLayout(); -} - -void Label::SetCenterWrap( bool bWrap ) -{ - m_bCenterWrap = bWrap; - _textImage->SetCenterWrap( m_bCenterWrap ); - - InvalidateLayout(); -} - -void Label::SetAllCaps( bool bAllCaps ) -{ - m_bAllCaps = bAllCaps; - _textImage->SetAllCaps( m_bAllCaps ); - - InvalidateLayout(); -} - -void Label::HandleAutoSizing( void ) -{ - if ( m_bAutoWideDirty ) - { - m_bAutoWideDirty = false; - - // Only change our width to match our content - int wide, tall; - GetContentSize(wide, tall); - SetSize(wide, GetTall()); - } -} - - - +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// memdbgon must be the last include file in a .cpp file!!! +#include + +using namespace vgui; + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +DECLARE_BUILD_FACTORY_DEFAULT_TEXT( Label, Label ); + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +Label::Label(Panel *parent, const char *panelName, const char *text) : BaseClass(parent, panelName) +{ + Init(); + + _textImage = new TextImage(text); + _textImage->SetColor(Color(0, 0, 0, 0)); + SetText(text); + _textImageIndex = AddImage(_textImage, 0); + + REGISTER_COLOR_AS_OVERRIDABLE( _disabledFgColor2, "disabledfgcolor2_override" ); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +Label::Label(Panel *parent, const char *panelName, const wchar_t *wszText) : BaseClass(parent, panelName) +{ + Init(); + + _textImage = new TextImage(wszText); + _textImage->SetColor(Color(0, 0, 0, 0)); + SetText(wszText); + _textImageIndex = AddImage(_textImage, 0); + + REGISTER_COLOR_AS_OVERRIDABLE( _disabledFgColor2, "disabledfgcolor2_override" ); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +Label::~Label() +{ + delete _textImage; + delete [] _associateName; + delete [] _fontOverrideName; +} + +//----------------------------------------------------------------------------- +// Purpose: Construct the label +//----------------------------------------------------------------------------- +void Label::Init() +{ + _contentAlignment = a_west; + _textColorState = CS_NORMAL; + _textInset[0] = 0; + _textInset[1] = 0; + _hotkey = 0; + _associate = NULL; + _associateName = NULL; + _fontOverrideName = NULL; + m_bWrap = false; + m_bCenterWrap = false; + m_bAutoWideToContents = false; + m_bUseProportionalInsets = false; + m_bAutoWideDirty = false; + +// SetPaintBackgroundEnabled(false); +} + +//----------------------------------------------------------------------------- +// Purpose: Set whether the text is displayed bright or dull +//----------------------------------------------------------------------------- +void Label::SetTextColorState(EColorState state) +{ + if (_textColorState != state) + { + _textColorState = state; + InvalidateLayout(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Return the full size of the contained content +//----------------------------------------------------------------------------- +void Label::GetContentSize(int &wide, int &tall) +{ + if( GetFont() == INVALID_FONT ) // we haven't loaded our font yet, so load it now + { + IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); + if ( pScheme ) + { + SetFont( pScheme->GetFont( "Default", IsProportional() ) ); + } + } + + + int tx0, ty0, tx1, ty1; + ComputeAlignment(tx0, ty0, tx1, ty1); + + // the +8 is padding to the content size + // the code which uses it should really set that itself; + // however a lot of existing code relies on this + wide = (tx1 - tx0) + _textInset[0]; + + // get the size of the text image and remove it + int iWide, iTall; + _textImage->GetSize(iWide, iTall); + wide -= iWide; + // get the full, untruncated (no elipsis) size of the text image. + _textImage->GetContentSize(iWide, iTall); + wide += iWide; + + // addin the image offsets as well + for (int i=0; i < _imageDar.Size(); i++) + wide += _imageDar[i].offset; + + tall = max((ty1 - ty0) + _textInset[1], iTall); +} + +//----------------------------------------------------------------------------- +// Purpose: Calculate the keyboard key that is a hotkey +//----------------------------------------------------------------------------- +wchar_t Label::CalculateHotkey(const char *text) +{ + for (const char *ch = text; *ch != 0; ch++) + { + if (*ch == '&') + { + // get the next character + ch++; + + if (*ch == '&') + { + // just an & + continue; + } + else if (*ch == 0) + { + break; + } + else if (V_isalnum(*ch)) + { + // found the hotkey + return (wchar_t)tolower(*ch); + } + } + } + + return '\0'; +} + +wchar_t Label::CalculateHotkey(const wchar_t *text) +{ + if( text ) + { + for (const wchar_t *ch = text; *ch != 0; ch++) + { + if (*ch == '&') + { + // get the next character + ch++; + + if (*ch == '&') + { + // just an & + continue; + } + else if (*ch == 0) + { + break; + } + else if (iswalnum(*ch)) + { + // found the hotkey + return (wchar_t)towlower(*ch); + } + } + } + } + + return '\0'; +} + +//----------------------------------------------------------------------------- +// Purpose: Check if this label has a hotkey that is the key passed in. +//----------------------------------------------------------------------------- +Panel *Label::HasHotkey(wchar_t key) +{ +#ifdef VGUI_HOTKEYS_ENABLED + if ( iswalnum( key ) ) + key = towlower( key ); + + if (_hotkey == key) + return this; +#endif + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Set the hotkey for this label +//----------------------------------------------------------------------------- +void Label::SetHotkey(wchar_t ch) +{ + _hotkey = ch; +} + +wchar_t Label::GetHotKey() +{ + return _hotkey; +} + +//----------------------------------------------------------------------------- +// Purpose: Handle a hotkey by passing on focus to associate +//----------------------------------------------------------------------------- +void Label::OnHotkeyPressed() +{ + // we can't accept focus, but if we are associated to a control give it to that + if (_associate.Get() && !IsBuildModeActive()) + { + _associate->RequestFocus(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Redirect mouse pressed to giving focus to associate +//----------------------------------------------------------------------------- +void Label::OnMousePressed(MouseCode code) +{ + if (_associate.Get() && !IsBuildModeActive()) + { + _associate->RequestFocus(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Return the text in the label +//----------------------------------------------------------------------------- +void Label::GetText(char *textOut, int bufferLen) +{ + _textImage->GetText(textOut, bufferLen); +} + +//----------------------------------------------------------------------------- +// Purpose: Return the text in the label +//----------------------------------------------------------------------------- +void Label::GetText(wchar_t *textOut, int bufLenInBytes) +{ + _textImage->GetText(textOut, bufLenInBytes); +} + +//----------------------------------------------------------------------------- +// Purpose: Take the string and looks it up in the localization file +// to convert it to unicode +// Setting the text will not set the size of the label. +// Set the size explicitly or use setToContent() +//----------------------------------------------------------------------------- +void Label::SetText(const char *text) +{ + // if set to null, just make blank + if (!text) + { + text = ""; + } + + // let the text image do the translation itself + _textImage->SetText(text); + + if( text[0] == '#' ) + { + SetHotkey(CalculateHotkey(g_pVGuiLocalize->Find(text))); + } + else + { + SetHotkey(CalculateHotkey(text)); + } + + m_bAutoWideDirty = m_bAutoWideToContents; + + InvalidateLayout(); + Repaint(); +} + +//----------------------------------------------------------------------------- +// Purpose: Set unicode text directly +//----------------------------------------------------------------------------- +void Label::SetText(const wchar_t *unicodeString, bool bClearUnlocalizedSymbol) +{ + m_bAutoWideDirty = m_bAutoWideToContents; + + if ( unicodeString && _textImage->GetUText() && !Q_wcscmp(unicodeString,_textImage->GetUText()) ) + return; + + _textImage->SetText(unicodeString, bClearUnlocalizedSymbol); + +//!! need to calculate hotkey from translated string + SetHotkey(CalculateHotkey(unicodeString)); + + InvalidateLayout(); // possible that the textimage needs to expand + Repaint(); +} + +//----------------------------------------------------------------------------- +// Purpose: updates localized text +//----------------------------------------------------------------------------- +void Label::OnDialogVariablesChanged(KeyValues *dialogVariables ) +{ + StringIndex_t index = _textImage->GetUnlocalizedTextSymbol(); + if (index != INVALID_LOCALIZE_STRING_INDEX) + { + // reconstruct the string from the variables + wchar_t buf[1024]; + g_pVGuiLocalize->ConstructString(buf, sizeof(buf), index, dialogVariables); + SetText(buf); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Additional offset at the Start of the text (from whichever side it is aligned) +//----------------------------------------------------------------------------- +void Label::SetTextInset(int xInset, int yInset) +{ + _textInset[0] = xInset; + _textInset[1] = yInset; + + int wide, tall; + GetSize( wide, tall); + _textImage->SetDrawWidth(wide - _textInset[0]); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Label::GetTextInset(int *xInset, int *yInset ) +{ + *xInset = _textInset[0]; + *yInset = _textInset[1]; +} + +//----------------------------------------------------------------------------- +// Purpose: Set the enabled state +//----------------------------------------------------------------------------- +void Label::SetEnabled(bool state) +{ + Panel::SetEnabled(state); +} + +//----------------------------------------------------------------------------- +// Purpose: Calculates where in the panel the content resides +// Input : &tx0 - [out] position of the content +// &ty0 - +// &tx1 - +// &ty1 - +// Note: horizontal alignment is west if the image dar has +// more than one image in it, this is because we use image sizes +// to determine layout in classes for example, Menu. +//----------------------------------------------------------------------------- +void Label::ComputeAlignment(int &tx0, int &ty0, int &tx1, int &ty1) +{ + int wide, tall; + GetPaintSize(wide, tall); + int tWide,tTall; + + // text bounding box + tx0 = 0; + ty0 = 0; + + // loop through all the images and calculate the complete bounds + int maxX = 0, maxY = 0; + + int actualXAlignment = _contentAlignment; + for (int i = 0; i < _imageDar.Count(); i++) + { + TImageInfo &imageInfo = _imageDar[i]; + IImage *image = imageInfo.image; + if (!image) + continue; // skip over null images + + // add up the bounds + int iWide, iTall; + image->GetSize(iWide, iTall); + if (iWide > wide) // if the image is larger than the label just do a west alignment + actualXAlignment = Label::a_west; + + // get the max height + maxY = max(maxY, iTall); + maxX += iWide; + + // add the offset to x + maxX += imageInfo.offset; + } + + tWide = maxX; + tTall = maxY; + + // x align text + switch (actualXAlignment) + { + // left + case Label::a_northwest: + case Label::a_west: + case Label::a_southwest: + { + tx0 = 0; + break; + } + // center + case Label::a_north: + case Label::a_center: + case Label::a_south: + { + tx0 = (wide - tWide) / 2; + break; + } + // right + case Label::a_northeast: + case Label::a_east: + case Label::a_southeast: + { + tx0 = wide - tWide; + break; + } + } + + // y align text + switch (_contentAlignment) + { + //top + case Label::a_northwest: + case Label::a_north: + case Label::a_northeast: + { + ty0 = 0; + break; + } + // center + case Label::a_west: + case Label::a_center: + case Label::a_east: + { + ty0 = (tall - tTall) / 2; + break; + } + // south + case Label::a_southwest: + case Label::a_south: + case Label::a_southeast: + { + ty0 = tall - tTall; + break; + } + } + + tx1 = tx0 + tWide; + ty1 = ty0 + tTall; +} + +//----------------------------------------------------------------------------- +// Purpose: overridden main drawing function for the panel +//----------------------------------------------------------------------------- +void Label::Paint() +{ + int tx0, ty0, tx1, ty1; + ComputeAlignment(tx0, ty0, tx1, ty1); + + // calculate who our associate is if we haven't already + if (_associateName) + { + SetAssociatedControl(FindSiblingByName(_associateName)); + delete [] _associateName; + _associateName = NULL; + } + + int labelWide, labelTall; + GetSize(labelWide, labelTall); + int x = tx0, y = _textInset[1] + ty0; + int imageYPos = 0; // a place to save the y offset for when we draw the disable version of the image + + // draw the set of images + for (int i = 0; i < _imageDar.Count(); i++) + { + TImageInfo &imageInfo = _imageDar[i]; + IImage *image = imageInfo.image; + if (!image) + continue; // skip over null images + + // add the offset to x + x += imageInfo.offset; + + // if this is the text image then add its inset to the left or from the right + if (i == _textImageIndex) + { + switch ( _contentAlignment ) + { + // left + case Label::a_northwest: + case Label::a_west: + case Label::a_southwest: + { + x += _textInset[0]; + break; + } + // right + case Label::a_northeast: + case Label::a_east: + case Label::a_southeast: + { + x -= _textInset[0]; + break; + } + } + } + + // see if the image is in a fixed position + if (imageInfo.xpos >= 0) + { + x = imageInfo.xpos; + } + + // draw + imageYPos = y; + image->SetPos(x, y); + + // fix up y for center-aligned text + if (_contentAlignment == Label::a_west || _contentAlignment == Label::a_center || _contentAlignment == Label::a_east) + { + int iw, it; + image->GetSize(iw, it); + if (it < (ty1 - ty0)) + { + imageYPos = ((ty1 - ty0) - it) / 2 + y; + image->SetPos(x, ((ty1 - ty0) - it) / 2 + y); + } + } + + // don't resize the image unless its too big + if (imageInfo.width >= 0) + { + int w, t; + image->GetSize(w, t); + if (w > imageInfo.width) + { + image->SetSize(imageInfo.width, t); + } + } + + // if it's the basic text image then draw specially + if (image == _textImage) + { + if (IsEnabled()) + { + if (_associate.Get() && ipanel()->HasParent(input()->GetFocus(), _associate->GetVPanel())) + { + _textImage->SetColor(_associateColor); + } + else + { + _textImage->SetColor(GetFgColor()); + } + + _textImage->Paint(); + } + else + { + // draw disabled version, with embossed look + // offset image + _textImage->SetPos(x + 1, imageYPos + 1); + _textImage->SetColor(_disabledFgColor1); + _textImage->Paint(); + + surface()->DrawFlushText(); + + // overlayed image + _textImage->SetPos(x, imageYPos); + _textImage->SetColor(_disabledFgColor2); + _textImage->Paint(); + } + } + else + { + image->Paint(); + } + + // add the image size to x + int wide, tall; + image->GetSize(wide, tall); + x += wide; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Helper function, draws a simple line with dashing parameters +//----------------------------------------------------------------------------- +void Label::DrawDashedLine(int x0, int y0, int x1, int y1, int dashLen, int gapLen) +{ + // work out which way the line goes + if ((x1 - x0) > (y1 - y0)) + { + // x direction line + while (1) + { + if (x0 + dashLen > x1) + { + // draw partial + surface()->DrawFilledRect(x0, y0, x1, y1); + } + else + { + surface()->DrawFilledRect(x0, y0, x0 + dashLen, y1); + } + + x0 += dashLen; + + if (x0 + gapLen > x1) + break; + + x0 += gapLen; + } + } + else + { + // y direction + while (1) + { + if (y0 + dashLen > y1) + { + // draw partial + surface()->DrawFilledRect(x0, y0, x1, y1); + } + else + { + surface()->DrawFilledRect(x0, y0, x1, y0 + dashLen); + } + + y0 += dashLen; + + if (y0 + gapLen > y1) + break; + + y0 += gapLen; + } + } +} + +void Label::SetContentAlignment(Alignment alignment) +{ + _contentAlignment=alignment; + Repaint(); +} + +//----------------------------------------------------------------------------- +// Purpose: Size the width of the label to its contents - only works from in ApplySchemeSettings or PerformLayout() +//----------------------------------------------------------------------------- +void Label::SizeToContents() +{ + int wide, tall; + GetContentSize(wide, tall); + + SetSize(wide, tall); +} + +//----------------------------------------------------------------------------- +// Purpose: Set the font the text is drawn in +//----------------------------------------------------------------------------- +void Label::SetFont(HFont font) +{ + _textImage->SetFont(font); + Repaint(); +} + +//----------------------------------------------------------------------------- +// Purpose: Resond to resizing of the panel +//----------------------------------------------------------------------------- +void Label::OnSizeChanged(int wide, int tall) +{ + InvalidateLayout(); + Panel::OnSizeChanged(wide, tall); +} + +//----------------------------------------------------------------------------- +// Purpose: Get the font the textImage is drawn in. +//----------------------------------------------------------------------------- +HFont Label::GetFont() +{ + return _textImage->GetFont(); +} + +//----------------------------------------------------------------------------- +// Purpose: Set the foreground color of the Label +//----------------------------------------------------------------------------- +void Label::SetFgColor(Color color) +{ + if (!(GetFgColor() == color)) + { + BaseClass::SetFgColor(color); + _textImage->SetColor(color); + Repaint(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Get the foreground color of the Label +//----------------------------------------------------------------------------- +Color Label::GetFgColor() +{ + Color clr = Panel::GetFgColor(); + return clr; +} + +//----------------------------------------------------------------------------- +// Purpose: Set the foreground color 1 color of the Label +//----------------------------------------------------------------------------- +void Label::SetDisabledFgColor1(Color color) +{ + _disabledFgColor1 = color; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Label::SetDisabledFgColor2(Color color) +{ + _disabledFgColor2 = color; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Color Label::GetDisabledFgColor1() +{ + return _disabledFgColor1; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Color Label::GetDisabledFgColor2() +{ + return _disabledFgColor2; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +TextImage *Label::GetTextImage() +{ + return _textImage; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool Label::RequestInfo(KeyValues *outputData) +{ + if (!stricmp(outputData->GetName(), "GetText")) + { + wchar_t wbuf[256]; + _textImage->GetText(wbuf, 255); + outputData->SetWString("text", wbuf); + return true; + } + + return Panel::RequestInfo(outputData); +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the text from the message +//----------------------------------------------------------------------------- +void Label::OnSetText(KeyValues *params) +{ + KeyValues *pkvText = params->FindKey("text", false); + if (!pkvText) + return; + + if (pkvText->GetDataType() == KeyValues::TYPE_STRING) + { + SetText(pkvText->GetString()); + } + else if (pkvText->GetDataType() == KeyValues::TYPE_WSTRING) + { + SetText(pkvText->GetWString()); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Add an image to the list +// returns the index the image was placed in +//----------------------------------------------------------------------------- +int Label::AddImage(IImage *image, int offset) +{ + int newImage = _imageDar.AddToTail(); + _imageDar[newImage].image = image; + _imageDar[newImage].offset = (short)offset; + _imageDar[newImage].xpos = -1; + _imageDar[newImage].width = -1; + InvalidateLayout(); + return newImage; +} + +//----------------------------------------------------------------------------- +// Purpose: removes all images from the list +// user is responsible for the memory +//----------------------------------------------------------------------------- +void Label::ClearImages() +{ + _imageDar.RemoveAll(); + _textImageIndex = -1; +} + +void Label::ResetToSimpleTextImage() +{ + ClearImages(); + _textImageIndex = AddImage(_textImage, 0); +} + + +//----------------------------------------------------------------------------- +// Purpose: Multiple image handling +// Images are drawn from left to right across the label, ordered by index +// By default there is a TextImage in position 0 +// Set the contents of an IImage in the IImage array. +//----------------------------------------------------------------------------- +void Label::SetImageAtIndex(int index, IImage *image, int offset) +{ + EnsureImageCapacity(index); +// Assert( image ); + + if ( _imageDar[index].image != image || _imageDar[index].offset != offset) + { + _imageDar[index].image = image; + _imageDar[index].offset = (short)offset; + InvalidateLayout(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Get an IImage in the IImage array. +//----------------------------------------------------------------------------- +IImage *Label::GetImageAtIndex(int index) +{ + if ( _imageDar.IsValidIndex( index ) ) + return _imageDar[index].image; + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Get the number of images in the array. +//----------------------------------------------------------------------------- +int Label::GetImageCount() +{ + return _imageDar.Count(); +} + +//----------------------------------------------------------------------------- +// Purpose: Move where the default text image is within the image array +// (it starts in position 0) +// Input : newIndex - +// Output : int - the index the default text image was previously in +//----------------------------------------------------------------------------- +int Label::SetTextImageIndex(int newIndex) +{ + if (newIndex == _textImageIndex) + return _textImageIndex; + + EnsureImageCapacity(newIndex); + + int oldIndex = _textImageIndex; + if ( _textImageIndex >= 0 ) + { + _imageDar[_textImageIndex].image = NULL; + } + if (newIndex > -1) + { + _imageDar[newIndex].image = _textImage; + } + _textImageIndex = newIndex; + return oldIndex; +} + +//----------------------------------------------------------------------------- +// Purpose: Ensure that the maxIndex will be a valid index +//----------------------------------------------------------------------------- +void Label::EnsureImageCapacity(int maxIndex) +{ + while (_imageDar.Size() <= maxIndex) + { + AddImage(NULL, 0); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Set the offset in pixels before the image +//----------------------------------------------------------------------------- +void Label::SetImagePreOffset(int index, int preOffset) +{ + if (_imageDar.IsValidIndex(index) && _imageDar[index].offset != preOffset) + { + _imageDar[index].offset = (short)preOffset; + InvalidateLayout(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: fixes the layout bounds of the image within the label +//----------------------------------------------------------------------------- +void Label::SetImageBounds(int index, int x, int width) +{ + _imageDar[index].xpos = (short)x; + _imageDar[index].width = (short)width; +} + +//----------------------------------------------------------------------------- +// Purpose: Labels can be associated with controls, and alter behaviour based on the associates behaviour +// If the associate is disabled, so are we +// If the associate has focus, we may alter how we draw +// If we get a hotkey press or focus message, we forward the focus to the associate +//----------------------------------------------------------------------------- +void Label::SetAssociatedControl(Panel *control) +{ + if (control != this) + { + _associate = control; + } + else + { + // don't let the associate ever be set to be ourself + _associate = NULL; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Called after a panel requests focus to fix up the whole chain +//----------------------------------------------------------------------------- +void Label::OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel) +{ + if (_associate.Get() && subFocus == GetVPanel() && !IsBuildModeActive()) + { + // we've received focus; pass the focus onto the associate instead + _associate->RequestFocus(); + } + else + { + BaseClass::OnRequestFocus(subFocus, defaultPanel); + } +} + +//----------------------------------------------------------------------------- +// Purpose: sets custom settings from the scheme file +//----------------------------------------------------------------------------- +void Label::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + if (_fontOverrideName) + { + // use the custom specified font since we have one set + SetFont(pScheme->GetFont(_fontOverrideName, IsProportional())); + } + if ( GetFont() == INVALID_FONT ) + { + SetFont( pScheme->GetFont( "Default", IsProportional() ) ); + } + + if ( m_bWrap || m_bCenterWrap ) + { + //tell it how big it is + int wide, tall; + Panel::GetSize(wide, tall); + wide -= _textInset[0]; // take inset into account + _textImage->SetSize(wide, tall); + + _textImage->RecalculateNewLinePositions(); + } + else + { + // if you don't set the size of the image, many, many buttons will break - we might want to look into fixing this all over the place later + int wide, tall; + _textImage->GetContentSize(wide, tall); + _textImage->SetSize(wide, tall); + } + + if ( m_bAutoWideToContents ) + { + m_bAutoWideDirty = true; + HandleAutoSizing(); + } + + // clear out any the images, since they will have been invalidated + for (int i = 0; i < _imageDar.Count(); i++) + { + IImage *image = _imageDar[i].image; + if (!image) + continue; // skip over null images + + if (i == _textImageIndex) + continue; + + _imageDar[i].image = NULL; + } + + SetDisabledFgColor1(GetSchemeColor("Label.DisabledFgColor1", pScheme)); + SetDisabledFgColor2(GetSchemeColor("Label.DisabledFgColor2", pScheme)); + SetBgColor(GetSchemeColor("Label.BgColor", pScheme)); + + switch (_textColorState) + { + case CS_DULL: + SetFgColor(GetSchemeColor("Label.TextDullColor", pScheme)); + break; + case CS_BRIGHT: + SetFgColor(GetSchemeColor("Label.TextBrightColor", pScheme)); + break; + case CS_NORMAL: + default: + SetFgColor(GetSchemeColor("Label.TextColor", pScheme)); + break; + } + + _associateColor = GetSchemeColor("Label.SelectedTextColor", pScheme); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Label::GetSettings( KeyValues *outResourceData ) +{ + // panel settings + Panel::GetSettings( outResourceData ); + + // label settings + char buf[256]; + _textImage->GetUnlocalizedText( buf, 255 ); + if (!strnicmp(buf, "#var_", 5)) + { + // strip off the variable prepender on save + outResourceData->SetString( "labelText", buf + 5 ); + } + else + { + outResourceData->SetString( "labelText", buf ); + } + + const char *alignmentString = ""; + switch ( _contentAlignment ) + { + case a_northwest: alignmentString = "north-west"; break; + case a_north: alignmentString = "north"; break; + case a_northeast: alignmentString = "north-east"; break; + case a_center: alignmentString = "center"; break; + case a_east: alignmentString = "east"; break; + case a_southwest: alignmentString = "south-west"; break; + case a_south: alignmentString = "south"; break; + case a_southeast: alignmentString = "south-east"; break; + case a_west: + default: alignmentString = "west"; break; + } + + outResourceData->SetString( "textAlignment", alignmentString ); + + if (_associate) + { + outResourceData->SetString("associate", _associate->GetName()); + } + + outResourceData->SetInt("dulltext", (int)(_textColorState == CS_DULL)); + outResourceData->SetInt("brighttext", (int)(_textColorState == CS_BRIGHT)); + + if (_fontOverrideName) + { + outResourceData->SetString("font", _fontOverrideName); + } + + outResourceData->SetInt("wrap", ( m_bWrap ? 1 : 0 )); + outResourceData->SetInt("centerwrap", ( m_bCenterWrap ? 1 : 0 )); + + if ( m_bUseProportionalInsets ) + { + outResourceData->SetInt("textinsetx", scheme()->GetProportionalNormalizedValueEx( GetScheme(), _textInset[0] ) ); + outResourceData->SetInt("textinsety", _textInset[1]); + } + else + { + outResourceData->SetInt("textinsetx", _textInset[0]); + outResourceData->SetInt("textinsety", _textInset[1]); + } + outResourceData->SetInt("auto_wide_tocontents", ( m_bAutoWideToContents ? 1 : 0 )); + outResourceData->SetInt("use_proportional_insets", ( m_bUseProportionalInsets ? 1 : 0 )); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Label::ApplySettings( KeyValues *inResourceData ) +{ + BaseClass::ApplySettings( inResourceData ); + + // label settings + const char *labelText = inResourceData->GetString( "labelText", NULL ); + if ( labelText ) + { + if (labelText[0] == '%' && labelText[strlen(labelText) - 1] == '%') + { + // it's a variable, set it to be a special variable localized string + wchar_t unicodeVar[256]; + g_pVGuiLocalize->ConvertANSIToUnicode(labelText, unicodeVar, sizeof(unicodeVar)); + + char var[256]; + _snprintf(var, sizeof(var), "#var_%s", labelText); + g_pVGuiLocalize->AddString(var + 1, unicodeVar, ""); + SetText(var); + } + else + { + SetText(labelText); + } + } + + // text alignment + const char *alignmentString = inResourceData->GetString( "textAlignment", "" ); + int align = -1; + + if ( !stricmp(alignmentString, "north-west") ) + { + align = a_northwest; + } + else if ( !stricmp(alignmentString, "north") ) + { + align = a_north; + } + else if ( !stricmp(alignmentString, "north-east") ) + { + align = a_northeast; + } + else if ( !stricmp(alignmentString, "west") ) + { + align = a_west; + } + else if ( !stricmp(alignmentString, "center") ) + { + align = a_center; + } + else if ( !stricmp(alignmentString, "east") ) + { + align = a_east; + } + else if ( !stricmp(alignmentString, "south-west") ) + { + align = a_southwest; + } + else if ( !stricmp(alignmentString, "south") ) + { + align = a_south; + } + else if ( !stricmp(alignmentString, "south-east") ) + { + align = a_southeast; + } + + if ( align != -1 ) + { + SetContentAlignment( (Alignment)align ); + } + + // the control we are to be associated with may not have been created yet, + // so keep a pointer to it's name and calculate it when we can + const char *associateName = inResourceData->GetString("associate", ""); + if (associateName[0] != 0) + { + int len = Q_strlen(associateName) + 1; + _associateName = new char[ len ]; + Q_strncpy( _associateName, associateName, len ); + } + + if (inResourceData->GetInt("dulltext", 0) == 1) + { + SetTextColorState(CS_DULL); + } + else if (inResourceData->GetInt("brighttext", 0) == 1) + { + SetTextColorState(CS_BRIGHT); + } + else + { + SetTextColorState(CS_NORMAL); + } + + // font settings + const char *overrideFont = inResourceData->GetString("font", ""); + IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); + + if (*overrideFont) + { + delete [] _fontOverrideName; + int len = Q_strlen(overrideFont) + 1; + _fontOverrideName = new char[ len ]; + Q_strncpy(_fontOverrideName, overrideFont, len ); + SetFont(pScheme->GetFont(_fontOverrideName, IsProportional())); + } + else if (_fontOverrideName) + { + delete [] _fontOverrideName; + _fontOverrideName = NULL; + SetFont(pScheme->GetFont("Default", IsProportional())); + } + + bool bWrapText = inResourceData->GetInt("centerwrap", 0) > 0; + SetCenterWrap( bWrapText ); + + m_bAutoWideToContents = inResourceData->GetInt("auto_wide_tocontents", 0) > 0; + + bWrapText = inResourceData->GetInt("wrap", 0) > 0; + SetWrap( bWrapText ); + + int inset_x = inResourceData->GetInt("textinsetx", _textInset[0]); + int inset_y = inResourceData->GetInt("textinsety", _textInset[1]); + // Had to play it safe and add a new key for backwards compatibility + m_bUseProportionalInsets = inResourceData->GetInt("use_proportional_insets", 0) > 0; + if ( m_bUseProportionalInsets ) + { + inset_x = scheme()->GetProportionalScaledValueEx( GetScheme(), inset_x ); + } + + SetTextInset( inset_x, inset_y ); + + bool bAllCaps = inResourceData->GetInt("allcaps", 0) > 0; + SetAllCaps( bAllCaps ); + + InvalidateLayout(true); +} + +//----------------------------------------------------------------------------- +// Purpose: Returns a description of the label string +//----------------------------------------------------------------------------- +const char *Label::GetDescription( void ) +{ + static char buf[1024]; + Q_snprintf(buf, sizeof(buf), "%s, string labelText, string associate, alignment textAlignment, int wrap, int dulltext, int brighttext, string font", BaseClass::GetDescription()); + return buf; +} + +//----------------------------------------------------------------------------- +// Purpose: If a label has images in _imageDar, the size +// must take those into account as well as the textImage part +// Textimage part will shrink ONLY if there is not enough room. +//----------------------------------------------------------------------------- +void Label::PerformLayout() +{ + int wide, tall; + Panel::GetSize(wide, tall); + wide -= _textInset[0]; // take inset into account + + // if we just have a textImage, this is trivial. + if (_imageDar.Count() == 1 && _textImageIndex == 0) + { + if ( m_bWrap || m_bCenterWrap ) + { + int twide, ttall; + _textImage->GetContentSize(twide, ttall); + _textImage->SetSize(wide, ttall); + } + else + { + int twide, ttall; + _textImage->GetContentSize(twide, ttall); + + // tell the textImage how much space we have to draw in + if ( wide < twide) + _textImage->SetSize(wide, ttall); + else + _textImage->SetSize(twide, ttall); + } + + HandleAutoSizing(); + + HandleAutoSizing(); + + return; + } + + // assume the images in the dar cannot be resized, and if + // the images + the textimage are too wide we shring the textimage part + if (_textImageIndex < 0) + return; + + // get the size of the images + int widthOfImages = 0; + for (int i = 0; i < _imageDar.Count(); i++) + { + TImageInfo &imageInfo = _imageDar[i]; + IImage *image = imageInfo.image; + if (!image) + continue; // skip over null images + + if (i == _textImageIndex) + continue; + + // add up the bounds + int iWide, iTall; + image->GetSize(iWide, iTall); + widthOfImages += iWide; + } + + // so this is how much room we have to draw the textimage part + int spaceAvail = wide - widthOfImages; + + // if we have no space at all just leave everything as is. + if (spaceAvail < 0) + return; + + int twide, ttall; + _textImage->GetSize (twide, ttall); + // tell the textImage how much space we have to draw in + _textImage->SetSize(spaceAvail, ttall); + + HandleAutoSizing(); +} + +void Label::SetWrap( bool bWrap ) +{ + m_bWrap = bWrap; + _textImage->SetWrap( m_bWrap ); + + InvalidateLayout(); +} + +void Label::SetCenterWrap( bool bWrap ) +{ + m_bCenterWrap = bWrap; + _textImage->SetCenterWrap( m_bCenterWrap ); + + InvalidateLayout(); +} + +void Label::SetAllCaps( bool bAllCaps ) +{ + m_bAllCaps = bAllCaps; + _textImage->SetAllCaps( m_bAllCaps ); + + InvalidateLayout(); +} + +void Label::HandleAutoSizing( void ) +{ + if ( m_bAutoWideDirty ) + { + m_bAutoWideDirty = false; + + // Only change our width to match our content + int wide, tall; + GetContentSize(wide, tall); + SetSize(wide, GetTall()); + } +} + + + -- cgit v1.2.3