diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/vgui2/vgui_controls/Label.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/vgui2/vgui_controls/Label.cpp')
| -rw-r--r-- | mp/src/vgui2/vgui_controls/Label.cpp | 1386 |
1 files changed, 1386 insertions, 0 deletions
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 <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <vgui/IInput.h>
+#include <vgui/ILocalize.h>
+#include <vgui/IPanel.h>
+#include <vgui/ISurface.h>
+#include <vgui/IScheme.h>
+#include <KeyValues.h>
+
+#include <vgui_controls/Label.h>
+#include <vgui_controls/Image.h>
+#include <vgui_controls/TextImage.h>
+#include <vgui_controls/Controls.h>
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+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());
+ }
+}
+
+
+
|