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

202 lines
4.9 KiB
C
Raw Normal View History

2014-02-13 15:21:02 +01:00
/********************************************************************
2014-02-14 09:40:53 +01:00
* Text field that allows multiple lines.
*
* Written by Dan Andersson, 2014
2014-02-13 15:21:02 +01:00
********************************************************************/
#ifndef DANBIAS_CLIENT_TEXT_FIELD_H
#define DANBIAS_CLIENT_TEXT_FIELD_H
2014-02-14 09:40:53 +01:00
#include <string>
#include <vector>
#include "ButtonRectangle.h"
#include "OysterMath.h"
#include "Utilities.h"
2014-02-13 15:21:02 +01:00
namespace DanBias { namespace Client
{
2014-02-14 09:40:53 +01:00
template<typename Owner>
class TextField : public ButtonRectangle<Owner>
2014-02-13 15:21:02 +01:00
{
public:
TextField();
2014-02-14 09:40:53 +01:00
TextField( ::std::wstring backgroundTexture, ::Oyster::Math::Float3 textColor, Owner owner, Oyster::Math::Float3 pos, Oyster::Math::Float2 size, ResizeAspectRatio resize = ResizeAspectRatio_Height );
virtual ~TextField();
2014-02-13 15:21:02 +01:00
2014-02-14 09:40:53 +01:00
virtual void RenderText();
2014-02-13 15:21:02 +01:00
2014-02-14 09:40:53 +01:00
const ::std::wstring & operator[]( unsigned int i ) const;
::std::wstring & operator[]( unsigned int i );
2014-02-13 15:21:02 +01:00
2014-02-14 12:09:59 +01:00
void SetFontHeight( ::Oyster::Math::Float h );
2014-02-14 09:40:53 +01:00
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;
2014-02-14 12:09:59 +01:00
::Oyster::Math::Float fontHeight, lineSpacing;
2014-02-14 09:40:53 +01:00
::std::vector<::std::wstring> lines;
2014-02-13 15:21:02 +01:00
};
2014-02-14 09:40:53 +01:00
// IMPLEMENTATIONS //////////////////////////////////////////////////
template<typename Owner>
TextField<Owner>::TextField()
: ButtonRectangle()
{
2014-02-14 12:09:59 +01:00
this->fontHeight = 0.025f;
2014-02-14 09:40:53 +01:00
this->lineSpacing = 0.001f;
this->isBottomAligned = true;
}
template<typename Owner>
TextField<Owner>::TextField( ::std::wstring backgroundTexture, ::Oyster::Math::Float3 textColor, Owner owner, Oyster::Math::Float3 pos, Oyster::Math::Float2 size, ResizeAspectRatio resize )
: ButtonRectangle( backgroundTexture, L"", textColor, owner, pos, size, resize )
{
2014-02-14 12:09:59 +01:00
this->fontHeight = 0.025f;
2014-02-14 09:40:53 +01:00
this->lineSpacing = 0.001f;
this->isBottomAligned = true;
}
template<typename Owner>
TextField<Owner>::~TextField() {}
template<typename Owner>
void TextField<Owner>::RenderText()
{
2014-02-14 12:09:59 +01:00
::Oyster::Math::Float lineStep = this->fontHeight + this->lineSpacing;
::Oyster::Math::Float2 rowSize = ::Oyster::Math::Float2( this->size.x, this->fontHeight );
2014-02-14 09:40:53 +01:00
if( this->isBottomAligned )
{
2014-02-14 12:09:59 +01:00
::Oyster::Math::Float3 topLeft = this->pos;
2014-02-14 09:40:53 +01:00
topLeft.y += this->size.y - lineStep;
auto line = this->lines.rbegin();
for( ; line != this->lines.rend(); ++line )
{
if( topLeft.y - lineStep >= this->pos.y )
{
2014-02-14 12:09:59 +01:00
::Oyster::Graphics::API::RenderText( (*line), topLeft, rowSize, this->fontHeight, this->textColor );
2014-02-14 09:40:53 +01:00
topLeft.y -= lineStep;
}
else break;
}
}
else
{
2014-02-14 12:09:59 +01:00
::Oyster::Math::Float3 topLeft = this->pos;
2014-02-14 09:40:53 +01:00
auto line = this->lines.begin();
for( ; line != this->lines.end(); ++line )
{
if( topLeft.y + lineStep < this->size.y )
{
2014-02-14 12:09:59 +01:00
::Oyster::Graphics::API::RenderText( (*line), topLeft, rowSize, this->fontHeight, this->textColor );
2014-02-14 09:40:53 +01:00
topLeft.y += lineStep;
}
else break;
}
}
}
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>
2014-02-14 12:09:59 +01:00
void TextField<Owner>::SetFontHeight( ::Oyster::Math::Float h )
2014-02-14 09:40:53 +01:00
{
2014-02-14 12:09:59 +01:00
this->fontHeight = h;
2014-02-14 09:40:53 +01:00
}
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();
2014-02-14 11:37:20 +01:00
for( ; line != split.end(); ++line )
2014-02-14 09:40:53 +01:00
{
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();
}
2014-02-13 15:21:02 +01:00
} }
#endif