Files
bullet3/examples/ThirdPartyLibs/Gwen/Controls/RichLabel.cpp
erwincoumans ab8f16961e Code-style consistency improvement:
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files.
make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type.
This commit contains no other changes aside from adding and applying clang-format-all.sh
2018-09-23 14:17:31 -07:00

207 lines
4.2 KiB
C++

/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Controls/RichLabel.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
const unsigned char Type_Text = 0;
const unsigned char Type_Newline = 1;
GWEN_CONTROL_CONSTRUCTOR(RichLabel)
{
m_bNeedsRebuild = false;
}
void RichLabel::AddLineBreak()
{
DividedText t;
t.type = Type_Newline;
m_TextBlocks.push_back(t);
}
void RichLabel::AddText(const Gwen::TextObject& text, Gwen::Color color, Gwen::Font* font)
{
if (text.m_Data.size() == 0) return;
Gwen::Utility::Strings::UnicodeList lst;
Gwen::Utility::Strings::Split(text.GetUnicode(), L"\n", lst, false);
for (size_t i = 0; i < lst.size(); i++)
{
if (i > 0) AddLineBreak();
DividedText t;
t.type = Type_Text;
t.text = lst[i];
t.color = color;
t.font = font;
m_TextBlocks.push_back(t);
m_bNeedsRebuild = true;
Invalidate();
}
}
bool RichLabel::SizeToChildren(bool w, bool h)
{
Rebuild();
return BaseClass::SizeToChildren(w, h);
}
void RichLabel::SplitLabel(const Gwen::UnicodeString& text, Gwen::Font* pFont, const DividedText& txt, int& x, int& y, int& lineheight)
{
Gwen::Utility::Strings::UnicodeList lst;
Gwen::Utility::Strings::Split(text, L" ", lst, true);
if (lst.size() == 0) return;
int iSpaceLeft = Width() - x;
// Does the whole word fit in?
{
Gwen::Point StringSize = GetSkin()->GetRender()->MeasureText(pFont, text);
if (iSpaceLeft > StringSize.x)
{
return CreateLabel(text, txt, x, y, lineheight, true);
}
}
// If the first word is bigger than the line, just give up.
{
Gwen::Point WordSize = GetSkin()->GetRender()->MeasureText(pFont, lst[0]);
if (WordSize.x >= iSpaceLeft)
{
CreateLabel(lst[0], txt, x, y, lineheight, true);
if (lst[0].size() >= text.size()) return;
Gwen::UnicodeString LeftOver = text.substr(lst[0].size() + 1);
return SplitLabel(LeftOver, pFont, txt, x, y, lineheight);
}
}
Gwen::UnicodeString strNewString = L"";
for (size_t i = 0; i < lst.size(); i++)
{
Gwen::Point WordSize = GetSkin()->GetRender()->MeasureText(pFont, strNewString + lst[i]);
if (WordSize.x > iSpaceLeft)
{
CreateLabel(strNewString, txt, x, y, lineheight, true);
x = 0;
y += lineheight;
break;
;
}
strNewString += lst[i];
}
Gwen::UnicodeString LeftOver = text.substr(strNewString.size() + 1);
return SplitLabel(LeftOver, pFont, txt, x, y, lineheight);
}
void RichLabel::CreateLabel(const Gwen::UnicodeString& text, const DividedText& txt, int& x, int& y, int& lineheight, bool NoSplit)
{
//
// Use default font or is one set?
//
Gwen::Font* pFont = GetSkin()->GetDefaultFont();
if (txt.font) pFont = txt.font;
//
// This string is too long for us, split it up.
//
Gwen::Point p = GetSkin()->GetRender()->MeasureText(pFont, text);
if (lineheight == -1)
{
lineheight = p.y;
}
if (!NoSplit)
{
if (x + p.x > Width())
{
return SplitLabel(text, pFont, txt, x, y, lineheight);
}
}
//
// Wrap
//
if (x + p.x >= Width())
{
CreateNewline(x, y, lineheight);
}
Gwen::Controls::Label* pLabel = new Gwen::Controls::Label(this);
pLabel->SetText(x == 0 ? Gwen::Utility::Strings::TrimLeft<Gwen::UnicodeString>(text, L" ") : text);
pLabel->SetTextColor(txt.color);
pLabel->SetFont(pFont);
pLabel->SizeToContents();
pLabel->SetPos(x, y);
//lineheight = (lineheight + pLabel->Height()) / 2;
x += pLabel->Width();
if (x >= Width())
{
CreateNewline(x, y, lineheight);
}
}
void RichLabel::CreateNewline(int& x, int& y, int& lineheight)
{
x = 0;
y += lineheight;
}
void RichLabel::Rebuild()
{
RemoveAllChildren();
int x = 0;
int y = 0;
int lineheight = -1;
for (DividedText::List::iterator it = m_TextBlocks.begin(); it != m_TextBlocks.end(); ++it)
{
if (it->type == Type_Newline)
{
CreateNewline(x, y, lineheight);
continue;
}
if (it->type == Type_Text)
{
CreateLabel((*it).text, *it, x, y, lineheight, false);
continue;
}
}
m_bNeedsRebuild = false;
}
void RichLabel::OnBoundsChanged(Gwen::Rect oldBounds)
{
BaseClass::OnBoundsChanged(oldBounds);
Rebuild();
}
void RichLabel::Layout(Gwen::Skin::Base* skin)
{
BaseClass::Layout(skin);
if (m_bNeedsRebuild)
{
Rebuild();
}
}