This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
MyGameFramework/lib/gwen/controls/gwen_richlabel.cpp
Gered c5cdddbeaa initial commit
current versions of all of my basic framework sources, build configurations/scripts, and supporting assets
2013-01-31 12:53:05 -05:00

209 lines
4.2 KiB
C++

/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "../gwen.h"
#include "gwen_richlabel.h"
#include "gwen_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.length() == 0 ) return;
Gwen::Utility::Strings::List lst;
Gwen::Utility::Strings::Split( text.Get(), "\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::String& text, Gwen::Font* pFont, const DividedText& txt, int& x, int& y, int& lineheight )
{
Gwen::Utility::Strings::List lst;
Gwen::Utility::Strings::Split( text, " ", 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::String LeftOver = text.substr( lst[0].size() + 1 );
return SplitLabel( LeftOver, pFont, txt, x, y, lineheight );
}
}
Gwen::String strNewString = "";
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::String LeftOver = text.substr( strNewString.size() + 1 );
return SplitLabel( LeftOver, pFont, txt, x, y, lineheight );
}
void RichLabel::CreateLabel( const Gwen::String& 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::String>( text, " " ) : 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();
}
}