usbloadergx/source/libwiigui/Text.cpp
2010-09-24 00:48:03 +00:00

328 lines
6.3 KiB
C++

#include "Text.hpp"
Text::Text(const char * t, int s, GXColor c) :
GuiText(t, s, c)
{
maxWidth = 400;
linestodraw = 9;
curLineStart = 0;
FirstLineOffset = 0;
wText = NULL;
if (!text) return;
wText = new (std::nothrow) wString(text);
if (!wText)
{
return;
}
if (wText->size() == 0)
{
wText->push_back(L' ');
wText->push_back(0);
}
textWidth = (font ? font : fontSystem)->getWidth(wText->data(), currentSize);
delete[] text;
text = NULL;
SetMaxWidth(maxWidth);
}
Text::Text(const wchar_t * t, int s, GXColor c) :
GuiText((wchar_t *) NULL, s, c)
{
maxWidth = 400;
linestodraw = 9;
curLineStart = 0;
FirstLineOffset = 0;
wText = NULL;
if (!t) return;
wText = new (std::nothrow) wString(t);
if (!wText)
{
return;
}
if (wText->size() == 0)
{
wText->push_back(L' ');
wText->push_back(0);
}
textWidth = (font ? font : fontSystem)->getWidth(wText->data(), currentSize);
SetMaxWidth(maxWidth);
}
Text::~Text()
{
if (wText) delete wText;
wText = NULL;
TextLines.clear();
ClearDynamicText();
}
void Text::SetText(const char * t)
{
wchar_t * tmp = charToWideChar(t);
if (!tmp) return;
if (wText) delete wText;
wText = new (std::nothrow) wString(tmp);
if (!wText)
{
return;
}
if (wText->size() == 0)
{
wText->push_back(L' ');
wText->push_back(0);
}
textWidth = (font ? font : fontSystem)->getWidth(wText->data(), currentSize);
delete[] tmp;
ClearDynamicText();
CalcLineOffsets();
}
void Text::SetText(const wchar_t * t)
{
if (!t) return;
if (wText) delete wText;
wText = new wString(t);
textWidth = (font ? font : fontSystem)->getWidth(wText->data(), currentSize);
CalcLineOffsets();
}
void Text::SetMaxWidth(int w)
{
maxWidth = w;
curLineStart = 0;
Refresh();
}
void Text::SetTextLine(int line)
{
if (line < 0)
line = 0;
else if (line > (int) TextLines.size() - 1) line = TextLines.size() - 1;
curLineStart = line;
FillRows();
while ((int) textDyn.size() < linestodraw && curLineStart > 0)
{
PreviousLine();
}
}
void Text::SetTextPos(int pos)
{
if (!wText) return;
int diff = 10000;
for (u32 i = 0; i < TextLines.size(); i++)
{
int curDiff = abs(TextLines[i].LineOffset - pos);
if (curDiff < diff)
{
diff = curDiff;
curLineStart = i;
}
}
FillRows();
while ((int) textDyn.size() < linestodraw && curLineStart > 0)
{
PreviousLine();
}
}
const wchar_t * Text::GetText()
{
return wText->c_str();
}
std::string Text::GetUTF8String(void) const
{
return wText->toUTF8();
}
int Text::GetLineOffset(int ind)
{
if (TextLines.size() == 0) return 0;
if (ind < 0) return TextLines[0].LineOffset;
if (ind >= (int) TextLines.size() - 1) return TextLines[TextLines.size() - 1].LineOffset;
return TextLines[ind].LineOffset;
}
const wchar_t * Text::GetTextLine(int ind)
{
if (filling || textDyn.size() == 0) return NULL;
if (ind < 0) return textDyn[0];
if (ind >= (int) textDyn.size()) return textDyn[textDyn.size() - 1];
return textDyn[ind];
}
void Text::Refresh()
{
CalcLineOffsets();
FillRows();
}
void Text::NextLine()
{
if (!wText || (curLineStart + 1 > ((int) TextLines.size() - linestodraw))) return;
++curLineStart;
FillRows();
}
void Text::PreviousLine()
{
if (!wText || curLineStart - 1 < 0) return;
--curLineStart;
FillRows();
}
void Text::FillRows()
{
if (!wText) return;
filling = true;
ClearDynamicText();
for (int i = 0; i < linestodraw && i < (int) TextLines.size(); i++)
{
if (i >= (int) textDyn.size())
{
textDyn.resize(i + 1);
textDyn[i] = new wchar_t[maxWidth];
}
int offset = TextLines[curLineStart + i].LineOffset;
int count = TextLines[curLineStart + i].CharCount + 1;
for (int n = 0; n < count && offset + n < (int) wText->size(); n++)
textDyn[i][n] = wText->at(offset + n);
textDyn[i][count] = 0;
}
filling = false;
return;
}
void Text::CalcLineOffsets()
{
if (!wText) return;
TextLines.clear();
TextLine TmpLine;
TmpLine.CharCount = 0;
TmpLine.LineOffset = 0;
TmpLine.width = 0;
const wchar_t * origTxt = wText->c_str();
int ch = 0;
int lastSpace = -1;
int lastSpaceIndex = -1;
int currWidth = 0;
int i = 0;
while (origTxt[ch])
{
currWidth += fontSystem->getCharWidth(origTxt[ch], currentSize, ch > 0 ? origTxt[ch - 1] : 0x0000);
if (currWidth >= maxWidth)
{
if (lastSpace > 0)
{
ch = lastSpace;
}
TmpLine.CharCount = ch - TmpLine.LineOffset;
TmpLine.width = currWidth;
TextLines.push_back(TmpLine);
currWidth = 0;
lastSpace = -1;
i = -1;
TmpLine.LineOffset = ch + 1;
}
else if (origTxt[ch] == '\n')
{
TmpLine.CharCount = ch - TmpLine.LineOffset;
TmpLine.width = currWidth;
TextLines.push_back(TmpLine);
currWidth = 0;
lastSpace = -1;
i = -1;
TmpLine.LineOffset = ch + 1;
}
else if (origTxt[ch] == ' ')
{
lastSpace = ch;
lastSpaceIndex = i;
}
ch++;
i++;
}
TmpLine.CharCount = ch - TmpLine.LineOffset;
TmpLine.width = currWidth;
if (TmpLine.CharCount > 0) TextLines.push_back(TmpLine);
}
void Text::Draw()
{
if (textDyn.size() == 0) return;
if (!this->IsVisible()) return;
GXColor c = color;
c.a = this->GetAlpha();
int newSize = size * GetScale();
if (newSize != currentSize)
{
currentSize = newSize;
if (wText) textWidth = (font ? font : fontSystem)->getWidth(wText->data(), currentSize);
}
u16 lineheight = newSize + 6;
for (u32 i = 0; i < textDyn.size(); i++)
{
if (!filling) (font ? font : fontSystem)->drawText(this->GetLeft(), this->GetTop() + i * lineheight, 0,
textDyn[i], currentSize, c, style, 0, maxWidth);
}
}