Danbias/Code/Game/GameClient/GameClientState/Buttons/TextField.h

201 lines
5.1 KiB
C++

/********************************************************************
* Text field that allows multiple lines.
*
* Written by Dan Andersson, 2014
********************************************************************/
#ifndef DANBIAS_CLIENT_TEXT_FIELD_H
#define DANBIAS_CLIENT_TEXT_FIELD_H
#include <string>
#include <vector>
#include "ButtonRectangle.h"
#include "OysterMath.h"
#include "Utilities.h"
namespace DanBias { namespace Client
{
template<typename Owner>
class TextField : public ButtonRectangle<Owner>
{
public:
TextField();
TextField( ::std::wstring backgroundTexture, ::Oyster::Math::Float4 textColor, ::Oyster::Math::Float4 backColor, Owner owner, Oyster::Math::Float3 pos, Oyster::Math::Float2 size, ResizeAspectRatio resize = ResizeAspectRatio_Height );
virtual ~TextField();
virtual void RenderText();
const ::std::wstring & operator[]( unsigned int i ) const;
::std::wstring & operator[]( unsigned int i );
void SetFontHeight( ::Oyster::Math::Float h );
void SetLineSpacing( ::Oyster::Math::Float ls );
void SetBottomAligned();
void SetTopAligned();
unsigned int GetNumLines() const;
unsigned int GetMaxLineLength() const;
void ReserveLines( unsigned int num );
void ClearText();
void AppendText( const ::std::wstring &text );
void PopBack();
void PopFront();
private:
bool isBottomAligned;
::Oyster::Math::Float fontHeight, lineSpacing;
::std::vector<::std::wstring> lines;
};
// IMPLEMENTATIONS //////////////////////////////////////////////////
template<typename Owner>
TextField<Owner>::TextField()
: ButtonRectangle()
{
this->fontHeight = 0.025f;
this->lineSpacing = 0.001f;
this->isBottomAligned = true;
}
template<typename Owner>
TextField<Owner>::TextField( ::std::wstring backgroundTexture, ::Oyster::Math::Float4 textColor, ::Oyster::Math::Float4 backColor, Owner owner, Oyster::Math::Float3 pos, Oyster::Math::Float2 size, ResizeAspectRatio resize )
: ButtonRectangle( backgroundTexture, L"", textColor, backColor, backColor, backColor, owner, pos, size, resize )
{
this->fontHeight = 0.025f;
this->lineSpacing = 0.001f;
this->isBottomAligned = true;
}
template<typename Owner>
TextField<Owner>::~TextField() {}
template<typename Owner>
void TextField<Owner>::RenderText()
{
::Oyster::Math::Float lineStep = this->fontHeight + this->lineSpacing;
::Oyster::Math::Float2 rowSize = ::Oyster::Math::Float2( this->size.x, this->fontHeight );
::Oyster::Math::Float3 fieldTopLeft = this->pos - Float3( this->size * 0.25f, 0.0f );
::Oyster::Math::Float3 topLeft = fieldTopLeft;
if( this->isBottomAligned )
{
topLeft.y += this->size.y - lineStep;
auto line = this->lines.rbegin();
for( ; line != this->lines.rend(); ++line )
{
if( topLeft.y < fieldTopLeft.y )
break;
::Oyster::Graphics::API::RenderText( (*line), topLeft, rowSize, this->fontHeight, this->textColor );
topLeft.y -= lineStep;
}
}
else
{
topLeft.y += this->lineSpacing;
auto line = this->lines.begin();
for( ; line != this->lines.end(); ++line )
{
if( topLeft.y >= fieldTopLeft.y + this->size.y )
break;
::Oyster::Graphics::API::RenderText( (*line), topLeft, rowSize, this->fontHeight, this->textColor );
topLeft.y += lineStep;
}
}
}
template<typename Owner>
const ::std::wstring & TextField<Owner>::operator[]( unsigned int i ) const
{
return this->lines[(::std::vector<::std::wstring>::size_type)i];
}
template<typename Owner>
::std::wstring & TextField<Owner>::operator[]( unsigned int i )
{
return this->lines[(::std::vector<::std::wstring>::size_type)i];
}
template<typename Owner>
void TextField<Owner>::SetFontHeight( ::Oyster::Math::Float h )
{
this->fontHeight = h;
}
template<typename Owner>
void TextField<Owner>::SetLineSpacing( ::Oyster::Math::Float ls )
{
this->lineSpacing = ls;
}
template<typename Owner>
void TextField<Owner>::SetBottomAligned()
{
this->isBottomAligned = true;
}
template<typename Owner>
void TextField<Owner>::SetTopAligned()
{
this->isBottomAligned = false;
}
template<typename Owner>
unsigned int TextField<Owner>::GetNumLines() const
{
return (unsigned int)this->lines.size();
}
template<typename Owner>
void TextField<Owner>::ReserveLines( unsigned int num )
{
this->lines.reserve( (::std::vector<::std::wstring>::size_type)num );
}
template<typename Owner>
void TextField<Owner>::ClearText()
{
this->lines.resize( 0 );
}
template<typename Owner>
void TextField<Owner>::AppendText( const ::std::wstring &text )
{
::std::vector<::std::wstring> split;
split.reserve( 10 );
::Utility::String::Split( split, text, L"\n", 0 );
auto line = split.begin();
for( ; line != split.end(); ++line )
{
this->lines.push_back( (*line) );
}
}
template<typename Owner>
void TextField<Owner>::PopBack()
{
this->lines.pop_back();
}
template<typename Owner>
void TextField<Owner>::PopFront()
{
::std::vector<::std::wstring>::size_type i = 0,
n = this->lines.size() - 1;
for( ; i < n; ++i )
{
this->lines[i] = this->lines[i+1];
}
this->lines.pop_back();
}
} }
#endif