mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-03 18:15:06 +01:00
9e79c9d99b
* code cleanup
601 lines
12 KiB
C++
601 lines
12 KiB
C++
/****************************************************************************
|
|
* libwiigui
|
|
*
|
|
* Tantric 2009
|
|
*
|
|
* gui_text.cpp
|
|
*
|
|
* GUI class definitions
|
|
***************************************************************************/
|
|
|
|
#include "gui.h"
|
|
#include "wstring.hpp"
|
|
|
|
#define MAX_LINES_TO_DRAW 9
|
|
|
|
static int presetSize = 18;
|
|
static int presetMaxWidth = 0;
|
|
static int presetAlignmentHor = 0;
|
|
static int presetAlignmentVert = 0;
|
|
static u16 presetStyle = 0;
|
|
static GXColor presetColor = ( GXColor ) {255, 255, 255, 255};
|
|
|
|
#define TEXT_SCROLL_DELAY 5
|
|
#define TEXT_SCROLL_INITIAL_DELAY 8
|
|
|
|
/**
|
|
* Constructor for the GuiText class.
|
|
*/
|
|
|
|
GuiText::GuiText( const char * t, int s, GXColor c )
|
|
{
|
|
text = NULL;
|
|
size = s;
|
|
currentSize = size;
|
|
color = c;
|
|
alpha = c.a;
|
|
style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE;
|
|
maxWidth = 0;
|
|
wrapMode = 0;
|
|
passChar = 0;
|
|
font = NULL;
|
|
linestodraw = MAX_LINES_TO_DRAW;
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
|
|
|
alignmentHor = ALIGN_CENTRE;
|
|
alignmentVert = ALIGN_MIDDLE;
|
|
|
|
if ( t )
|
|
{
|
|
text = charToWideChar( t );
|
|
if ( !text )
|
|
return;
|
|
|
|
textWidth = fontSystem->getWidth( text, currentSize );
|
|
}
|
|
}
|
|
|
|
GuiText::GuiText( const wchar_t * t, int s, GXColor c )
|
|
{
|
|
text = NULL;
|
|
size = s;
|
|
currentSize = size;
|
|
color = c;
|
|
alpha = c.a;
|
|
style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE;
|
|
maxWidth = 0;
|
|
wrapMode = 0;
|
|
passChar = 0;
|
|
font = NULL;
|
|
linestodraw = MAX_LINES_TO_DRAW;
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
|
|
|
alignmentHor = ALIGN_CENTRE;
|
|
alignmentVert = ALIGN_MIDDLE;
|
|
|
|
if ( t )
|
|
{
|
|
text = new ( std::nothrow ) wchar_t[wcslen( t )+1];
|
|
if ( !text )
|
|
return;
|
|
|
|
wcscpy( text, t );
|
|
|
|
textWidth = fontSystem->getWidth( text, currentSize );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructor for the GuiText class, uses presets
|
|
*/
|
|
GuiText::GuiText( const char * t )
|
|
{
|
|
text = NULL;
|
|
size = presetSize;
|
|
currentSize = size;
|
|
color = presetColor;
|
|
alpha = presetColor.a;
|
|
style = presetStyle;
|
|
maxWidth = presetMaxWidth;
|
|
wrapMode = 0;
|
|
passChar = 0;
|
|
font = NULL;
|
|
linestodraw = MAX_LINES_TO_DRAW;
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
|
|
|
alignmentHor = presetAlignmentHor;
|
|
alignmentVert = presetAlignmentVert;
|
|
|
|
if ( t )
|
|
{
|
|
text = charToWideChar( t );
|
|
if ( !text )
|
|
return;
|
|
|
|
textWidth = fontSystem->getWidth( text, currentSize );
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Destructor for the GuiText class.
|
|
*/
|
|
GuiText::~GuiText()
|
|
{
|
|
if ( text )
|
|
delete [] text;
|
|
text = NULL;
|
|
|
|
if ( font )
|
|
{
|
|
delete font;
|
|
font = NULL;
|
|
}
|
|
|
|
ClearDynamicText();
|
|
}
|
|
|
|
void GuiText::SetText( const char * t )
|
|
{
|
|
LOCK( this );
|
|
|
|
if ( text )
|
|
delete [] text;
|
|
text = NULL;
|
|
|
|
ClearDynamicText();
|
|
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
|
|
if ( t )
|
|
{
|
|
text = charToWideChar( t );
|
|
if ( !text )
|
|
return;
|
|
|
|
if ( passChar != 0 )
|
|
{
|
|
for ( u8 i = 0; i < wcslen( text ); i++ )
|
|
text[i] = passChar;
|
|
}
|
|
|
|
textWidth = fontSystem->getWidth( text, currentSize );
|
|
}
|
|
}
|
|
|
|
void GuiText::SetTextf( const char *format, ... )
|
|
{
|
|
if ( !format )
|
|
SetText( ( char * ) NULL );
|
|
|
|
char *tmp = 0;
|
|
va_list va;
|
|
va_start( va, format );
|
|
if ( ( vasprintf( &tmp, format, va ) >= 0 ) && tmp )
|
|
{
|
|
SetText( tmp );
|
|
}
|
|
va_end( va );
|
|
|
|
if ( tmp )
|
|
free( tmp );
|
|
}
|
|
|
|
|
|
void GuiText::SetText( const wchar_t * t )
|
|
{
|
|
LOCK( this );
|
|
|
|
if ( text )
|
|
delete [] text;
|
|
text = NULL;
|
|
|
|
ClearDynamicText();
|
|
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
|
|
if ( t )
|
|
{
|
|
text = new ( std::nothrow ) wchar_t[wcslen( t )+1];
|
|
if ( !text )
|
|
return;
|
|
|
|
wcscpy( text, t );
|
|
|
|
if ( passChar != 0 )
|
|
{
|
|
for ( u8 i = 0; i < wcslen( text ); i++ )
|
|
text[i] = passChar;
|
|
}
|
|
|
|
textWidth = fontSystem->getWidth( text, currentSize );
|
|
}
|
|
}
|
|
|
|
void GuiText::ClearDynamicText()
|
|
{
|
|
for ( u32 i = 0; i < textDyn.size(); i++ )
|
|
{
|
|
if ( textDyn[i] )
|
|
delete [] textDyn[i];
|
|
}
|
|
textDyn.clear();
|
|
}
|
|
|
|
void GuiText::SetPresets( int sz, GXColor c, int w, u16 s, int h, int v )
|
|
{
|
|
presetSize = sz;
|
|
presetColor = c;
|
|
presetStyle = s;
|
|
presetMaxWidth = w;
|
|
presetAlignmentHor = h;
|
|
presetAlignmentVert = v;
|
|
}
|
|
|
|
void GuiText::SetFontSize( int s )
|
|
{
|
|
LOCK( this );
|
|
|
|
size = s;
|
|
}
|
|
|
|
void GuiText::SetMaxWidth( int width, int w )
|
|
{
|
|
LOCK( this );
|
|
|
|
maxWidth = width;
|
|
wrapMode = w;
|
|
|
|
if ( w == SCROLL_HORIZONTAL )
|
|
{
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
|
}
|
|
|
|
ClearDynamicText();
|
|
}
|
|
|
|
void GuiText::SetPassChar( wchar_t p )
|
|
{
|
|
LOCK( this );
|
|
passChar = p;
|
|
}
|
|
|
|
void GuiText::SetColor( GXColor c )
|
|
{
|
|
LOCK( this );
|
|
color = c;
|
|
alpha = c.a;
|
|
}
|
|
|
|
void GuiText::SetStyle( u16 s )
|
|
{
|
|
LOCK( this );
|
|
style = s;
|
|
}
|
|
|
|
void GuiText::SetAlignment( int hor, int vert )
|
|
{
|
|
LOCK( this );
|
|
style = 0;
|
|
|
|
switch ( hor )
|
|
{
|
|
case ALIGN_LEFT:
|
|
style |= FTGX_JUSTIFY_LEFT;
|
|
break;
|
|
case ALIGN_RIGHT:
|
|
style |= FTGX_JUSTIFY_RIGHT;
|
|
break;
|
|
default:
|
|
style |= FTGX_JUSTIFY_CENTER;
|
|
break;
|
|
}
|
|
switch ( vert )
|
|
{
|
|
case ALIGN_TOP:
|
|
style |= FTGX_ALIGN_TOP;
|
|
break;
|
|
case ALIGN_BOTTOM:
|
|
style |= FTGX_ALIGN_BOTTOM;
|
|
break;
|
|
default:
|
|
style |= FTGX_ALIGN_MIDDLE;
|
|
break;
|
|
}
|
|
|
|
alignmentHor = hor;
|
|
alignmentVert = vert;
|
|
}
|
|
|
|
void GuiText::SetLinesToDraw( int l )
|
|
{
|
|
linestodraw = l;
|
|
}
|
|
|
|
int GuiText::GetTextWidth()
|
|
{
|
|
if ( !text )
|
|
return 0;
|
|
|
|
return fontSystem->getWidth( text, currentSize );
|
|
}
|
|
|
|
int GuiText::GetTextWidth( int ind )
|
|
{
|
|
if ( ind < 0 || ind >= ( int ) textDyn.size() )
|
|
return this->GetTextWidth();
|
|
|
|
return fontSystem->getWidth( textDyn[ind], currentSize );
|
|
}
|
|
|
|
int GuiText::GetTextMaxWidth()
|
|
{
|
|
return maxWidth;
|
|
}
|
|
|
|
const wchar_t * GuiText::GetDynText( int ind )
|
|
{
|
|
if ( ind < 0 || ind >= ( int ) textDyn.size() )
|
|
return text;
|
|
|
|
return textDyn[ind];
|
|
}
|
|
|
|
const wchar_t * GuiText::GetText()
|
|
{
|
|
return text;
|
|
}
|
|
|
|
/**
|
|
* Change font
|
|
*/
|
|
bool GuiText::SetFont( const u8 *fontbuffer, const u32 filesize )
|
|
{
|
|
if ( !fontbuffer || !filesize )
|
|
return false;
|
|
|
|
LOCK( this );
|
|
if ( font )
|
|
{
|
|
delete font;
|
|
font = NULL;
|
|
}
|
|
font = new FreeTypeGX( fontbuffer, filesize );
|
|
textWidth = font->getWidth( text, currentSize );
|
|
|
|
return true;
|
|
}
|
|
|
|
void GuiText::MakeDottedText()
|
|
{
|
|
int pos = textDyn.size();
|
|
textDyn.resize( pos + 1 );
|
|
|
|
int i = 0, currentWidth = 0;
|
|
textDyn[pos] = new wchar_t[maxWidth];
|
|
|
|
while ( text[i] )
|
|
{
|
|
currentWidth += ( font ? font : fontSystem )->getCharWidth( text[i], currentSize, i > 0 ? text[i-1] : 0x0000 );
|
|
if ( currentWidth >= maxWidth )
|
|
{
|
|
if ( i > 3 )
|
|
{
|
|
textDyn[pos][i-3] = '.';
|
|
textDyn[pos][i-2] = '.';
|
|
textDyn[pos][i-1] = '.';
|
|
}
|
|
break;
|
|
}
|
|
|
|
textDyn[pos][i] = text[i];
|
|
|
|
i++;
|
|
}
|
|
textDyn[pos][i] = 0;
|
|
}
|
|
|
|
void GuiText::ScrollText()
|
|
{
|
|
if ( textDyn.size() == 0 )
|
|
{
|
|
int pos = textDyn.size();
|
|
int i = 0, currentWidth = 0;
|
|
textDyn.resize( pos + 1 );
|
|
|
|
textDyn[pos] = new wchar_t[maxWidth];
|
|
|
|
while ( text[i] && currentWidth < maxWidth )
|
|
{
|
|
textDyn[pos][i] = text[i];
|
|
|
|
currentWidth += ( font ? font : fontSystem )->getCharWidth( text[i], currentSize, i > 0 ? text[i-1] : 0x0000 );
|
|
|
|
++i;
|
|
}
|
|
textDyn[pos][i] = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
if ( frameCount % textScrollDelay != 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( textScrollInitialDelay )
|
|
{
|
|
--textScrollInitialDelay;
|
|
return;
|
|
}
|
|
|
|
int strlen = wcslen( text );
|
|
|
|
++textScrollPos;
|
|
if ( textScrollPos > strlen )
|
|
{
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
}
|
|
|
|
int ch = textScrollPos;
|
|
int pos = textDyn.size() - 1;
|
|
|
|
if ( textDyn[pos] )
|
|
delete [] textDyn[pos];
|
|
|
|
textDyn[pos] = new wchar_t[maxWidth];
|
|
|
|
int i = 0, currentWidth = 0;
|
|
|
|
while ( currentWidth < maxWidth )
|
|
{
|
|
if ( ch > strlen - 1 )
|
|
{
|
|
textDyn[pos][i++] = ' ';
|
|
textDyn[pos][i++] = ' ';
|
|
textDyn[pos][i++] = ' ';
|
|
ch = 0;
|
|
}
|
|
|
|
textDyn[pos][i] = text[ch];
|
|
++ch;
|
|
++i;
|
|
|
|
currentWidth += ( font ? font : fontSystem )->getCharWidth( text[ch], currentSize, ch > 0 ? text[ch-1] : 0x0000 );
|
|
}
|
|
textDyn[pos][i] = 0;
|
|
}
|
|
|
|
void GuiText::WrapText()
|
|
{
|
|
if ( textDyn.size() > 0 )
|
|
return;
|
|
|
|
int i = 0;
|
|
int ch = 0;
|
|
int linenum = 0;
|
|
int lastSpace = -1;
|
|
int lastSpaceIndex = -1;
|
|
int currentWidth = 0;
|
|
|
|
while ( text[ch] && linenum < linestodraw )
|
|
{
|
|
if ( linenum >= ( int ) textDyn.size() )
|
|
{
|
|
textDyn.resize( linenum + 1 );
|
|
textDyn[linenum] = new wchar_t[maxWidth];
|
|
}
|
|
|
|
textDyn[linenum][i] = text[ch];
|
|
textDyn[linenum][i+1] = 0;
|
|
|
|
currentWidth += ( font ? font : fontSystem )->getCharWidth( text[ch], currentSize, ch > 0 ? text[ch-1] : 0x0000 );
|
|
|
|
if ( currentWidth >= maxWidth )
|
|
{
|
|
if ( lastSpace >= 0 )
|
|
{
|
|
textDyn[linenum][lastSpaceIndex] = 0; // discard space, and everything after
|
|
ch = lastSpace; // go backwards to the last space
|
|
lastSpace = -1; // we have used this space
|
|
lastSpaceIndex = -1;
|
|
}
|
|
|
|
if ( linenum + 1 == linestodraw && text[ch+1] != 0x0000 )
|
|
{
|
|
textDyn[linenum][i-2] = '.';
|
|
textDyn[linenum][i-1] = '.';
|
|
textDyn[linenum][i] = '.';
|
|
textDyn[linenum][i+1] = 0;
|
|
}
|
|
|
|
currentWidth = 0;
|
|
++linenum;
|
|
i = -1;
|
|
}
|
|
if ( text[ch] == ' ' && i >= 0 )
|
|
{
|
|
lastSpace = ch;
|
|
lastSpaceIndex = i;
|
|
}
|
|
++ch;
|
|
++i;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw the text on screen
|
|
*/
|
|
void GuiText::Draw()
|
|
{
|
|
if ( !text )
|
|
return;
|
|
|
|
if ( !IsVisible() )
|
|
return;
|
|
|
|
GXColor c = color;
|
|
c.a = GetAlpha();
|
|
|
|
int newSize = size * GetScale();
|
|
|
|
if ( newSize != currentSize )
|
|
{
|
|
currentSize = newSize;
|
|
|
|
if ( text )
|
|
textWidth = ( font ? font : fontSystem )->getWidth( text, currentSize );
|
|
}
|
|
|
|
if ( maxWidth > 0 && maxWidth <= textWidth )
|
|
{
|
|
if ( wrapMode == DOTTED ) // text dotted
|
|
{
|
|
if ( textDyn.size() == 0 )
|
|
MakeDottedText();
|
|
|
|
if ( textDyn.size() > 0 )
|
|
( font ? font : fontSystem )->drawText( this->GetLeft(), this->GetTop(), 0, textDyn[textDyn.size()-1], currentSize, c, style );
|
|
}
|
|
|
|
else if ( wrapMode == SCROLL_HORIZONTAL )
|
|
{
|
|
ScrollText();
|
|
|
|
if ( textDyn.size() > 0 )
|
|
( font ? font : fontSystem )->drawText( this->GetLeft(), this->GetTop(), 0, textDyn[textDyn.size()-1], currentSize, c, style );
|
|
}
|
|
else if ( wrapMode == WRAP )
|
|
{
|
|
int lineheight = currentSize + 6;
|
|
int voffset = 0;
|
|
if ( alignmentVert == ALIGN_MIDDLE )
|
|
voffset = -( lineheight * textDyn.size() ) / 2 + lineheight / 2;
|
|
|
|
if ( textDyn.size() == 0 )
|
|
WrapText();
|
|
|
|
for ( u32 i = 0; i < textDyn.size(); i++ )
|
|
{
|
|
( font ? font : fontSystem )->drawText( this->GetLeft(), this->GetTop() + voffset + i*lineheight, 0, textDyn[i], currentSize, c, style );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
( font ? font : fontSystem )->drawText( this->GetLeft(), this->GetTop(), 0, text, currentSize, c, style, textWidth );
|
|
}
|
|
this->UpdateEffects();
|
|
}
|