From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- mp/src/vgui2/vgui_controls/Label.cpp | 1386 ++++++++++++++++++++++++++++++++++ 1 file changed, 1386 insertions(+) create mode 100644 mp/src/vgui2/vgui_controls/Label.cpp (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 new file mode 100644 index 00000000..26199308 --- /dev/null +++ b/mp/src/vgui2/vgui_controls/Label.cpp @@ -0,0 +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()); + } +} + + + -- cgit v1.2.3