Commit 777ea019 authored by hybrid's avatar hybrid

Adding a new flag and new text break for support of right-to-left text in...

Adding a new flag and new text break for support of right-to-left text in StaticText elements. Patch from Auria and STK project.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3585 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 658cc282
...@@ -97,6 +97,17 @@ namespace gui ...@@ -97,6 +97,17 @@ namespace gui
//! Checks if the text in this label should be clipped if it goes outside bounds //! Checks if the text in this label should be clipped if it goes outside bounds
virtual bool isTextRestrainedInside() const = 0; virtual bool isTextRestrainedInside() const = 0;
//! Set whether the string should be interpreted as right-to-left (RTL) text
/** \note This component does not implement the Unicode bidi standard, the
text of the component should be already RTL if you call this. The
main difference when RTL is enabled is that the linebreaks for multiline
elements are performed starting from the end.
*/
virtual void setRightToLeft(bool rtl) = 0;
//! Checks whether the text in this element should be interpreted as right-to-left
virtual bool isRightToLeft() const = 0;
}; };
......
...@@ -256,6 +256,18 @@ bool CGUIStaticText::isWordWrapEnabled() const ...@@ -256,6 +256,18 @@ bool CGUIStaticText::isWordWrapEnabled() const
} }
void CGUIStaticText::setRightToLeft(bool rtl)
{
RightToLeft = rtl;
}
bool CGUIStaticText::isRightToLeft() const
{
return RightToLeft;
}
//! Breaks the single text line. //! Breaks the single text line.
void CGUIStaticText::breakText() void CGUIStaticText::breakText()
{ {
...@@ -275,87 +287,179 @@ void CGUIStaticText::breakText() ...@@ -275,87 +287,179 @@ void CGUIStaticText::breakText()
LastBreakFont = font; LastBreakFont = font;
core::stringw line; // We have to deal with right-to-left and left-to-right differently
core::stringw word; // However, most parts of the following code is the same, it's just
core::stringw whitespace; // some order and boundaries which change.
s32 size = Text.size(); if (!RightToLeft)
s32 length = 0;
s32 elWidth = RelativeRect.getWidth() - 6;
wchar_t c;
for (s32 i=0; i<size; ++i)
{ {
c = Text[i]; // regular (left-to-right)
bool lineBreak = false; core::stringw line;
core::stringw word;
if (c == L'\r') // Mac or Windows breaks core::stringw whitespace;
s32 size = Text.size();
s32 length = 0;
s32 elWidth = RelativeRect.getWidth() - 6;
wchar_t c;
for (s32 i=0; i<size; ++i)
{ {
lineBreak = true; c = Text[i];
if (Text[i+1] == L'\n') // Windows breaks bool lineBreak = false;
if (c == L'\r') // Mac or Windows breaks
{ {
Text.erase(i+1); lineBreak = true;
--size; if (Text[i+1] == L'\n') // Windows breaks
{
Text.erase(i+1);
--size;
}
c = '\0';
} }
c = '\0'; else if (c == L'\n') // Unix breaks
}
else if (c == L'\n') // Unix breaks
{
lineBreak = true;
c = '\0';
}
if (c == L' ' || c == 0 || i == (size-1))
{
if (word.size())
{ {
// here comes the next whitespace, look if lineBreak = true;
// we must break the last word to the next line. c = '\0';
const s32 whitelgth = font->getDimension(whitespace.c_str()).Width; }
const s32 wordlgth = font->getDimension(word.c_str()).Width;
if (length && (length + wordlgth + whitelgth > elWidth)) if (c==L' ' || c==0 || i==(size-1))
{
if (word.size())
{ {
// break to next line // here comes the next whitespace, look if
BrokenText.push_back(line); // we must break the last word to the next line.
length = wordlgth; const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
line = word; const s32 wordlgth = font->getDimension(word.c_str()).Width;
if (length && (length + wordlgth + whitelgth > elWidth))
{
// break to next line
BrokenText.push_back(line);
length = wordlgth;
line = word;
}
else
{
// add word to line
line += whitespace;
line += word;
length += whitelgth + wordlgth;
}
word = L"";
whitespace = L"";
} }
else
whitespace += c;
// compute line break
if (lineBreak)
{ {
// add word to line
line += whitespace; line += whitespace;
line += word; line += word;
length += whitelgth + wordlgth; BrokenText.push_back(line);
line = L"";
word = L"";
whitespace = L"";
length = 0;
} }
}
else
{
// yippee this is a word..
word += c;
}
}
line += whitespace;
line += word;
BrokenText.push_back(line);
}
else
{
// right-to-left
core::stringw line;
core::stringw word;
core::stringw whitespace;
s32 size = Text.size();
s32 length = 0;
s32 elWidth = RelativeRect.getWidth() - 6;
wchar_t c;
for (s32 i=size; i>=0; --i)
{
c = Text[i];
bool lineBreak = false;
word = L""; if (c == L'\r') // Mac or Windows breaks
whitespace = L""; {
lineBreak = true;
if ((i>0) && Text[i-1] == L'\n') // Windows breaks
{
Text.erase(i-1);
--size;
}
c = '\0';
}
else if (c == L'\n') // Unix breaks
{
lineBreak = true;
c = '\0';
} }
whitespace += c; if (c==L' ' || c==0 || i==0)
{
if (word.size())
{
// here comes the next whitespace, look if
// we must break the last word to the next line.
const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
const s32 wordlgth = font->getDimension(word.c_str()).Width;
if (length && (length + wordlgth + whitelgth > elWidth))
{
// break to next line
BrokenText.push_back(line);
length = wordlgth;
line = word;
}
else
{
// add word to line
line = whitespace + line;
line = word + line;
length += whitelgth + wordlgth;
}
// compute line break word = L"";
if (lineBreak) whitespace = L"";
}
whitespace = core::stringw(&c, 1) + whitespace;
// compute line break
if (lineBreak)
{
line = whitespace + line;
line = word + line;
BrokenText.push_back(line);
line = L"";
word = L"";
whitespace = L"";
length = 0;
}
}
else
{ {
line += whitespace; // yippee this is a word..
line += word; word = core::stringw(&c, 1) + word;
BrokenText.push_back(line);
line = L"";
word = L"";
whitespace = L"";
length = 0;
} }
} }
else
{
// yippee this is a word..
word += c;
}
}
line += whitespace; line = whitespace + line;
line += word; line = word + line;
BrokenText.push_back(line); BrokenText.push_back(line);
}
} }
...@@ -445,6 +549,7 @@ void CGUIStaticText::serializeAttributes(io::IAttributes* out, io::SAttributeRea ...@@ -445,6 +549,7 @@ void CGUIStaticText::serializeAttributes(io::IAttributes* out, io::SAttributeRea
out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled); out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled);
out->addBool ("WordWrap", WordWrap); out->addBool ("WordWrap", WordWrap);
out->addBool ("Background", Background); out->addBool ("Background", Background);
out->addBool ("RightToLeft", RightToLeft);
out->addBool ("RestrainTextInside", RestrainTextInside); out->addBool ("RestrainTextInside", RestrainTextInside);
out->addColor ("OverrideColor", OverrideColor); out->addColor ("OverrideColor", OverrideColor);
out->addColor ("BGColor", BGColor); out->addColor ("BGColor", BGColor);
...@@ -465,6 +570,7 @@ void CGUIStaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeRe ...@@ -465,6 +570,7 @@ void CGUIStaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeRe
OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled"); OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled");
setWordWrap(in->getAttributeAsBool("WordWrap")); setWordWrap(in->getAttributeAsBool("WordWrap"));
Background = in->getAttributeAsBool("Background"); Background = in->getAttributeAsBool("Background");
RightToLeft = in->getAttributeAsBool("RightToLeft");
RestrainTextInside = in->getAttributeAsBool("RestrainTextInside"); RestrainTextInside = in->getAttributeAsBool("RestrainTextInside");
OverrideColor = in->getAttributeAsColor("OverrideColor"); OverrideColor = in->getAttributeAsColor("OverrideColor");
BGColor = in->getAttributeAsColor("BGColor"); BGColor = in->getAttributeAsColor("BGColor");
......
...@@ -86,6 +86,17 @@ namespace gui ...@@ -86,6 +86,17 @@ namespace gui
//! Updates the absolute position, splits text if word wrap is enabled //! Updates the absolute position, splits text if word wrap is enabled
virtual void updateAbsolutePosition(); virtual void updateAbsolutePosition();
//! Set whether the string should be interpreted as right-to-left (RTL) text
/** \note This component does not implement the Unicode bidi standard, the
text of the component should be already RTL if you call this. The
main difference when RTL is enabled is that the linebreaks for multiline
elements are performed starting from the end.
*/
virtual void setRightToLeft(bool rtl);
//! Checks if the text should be interpreted as right-to-left text
virtual bool isRightToLeft() const;
//! Writes attributes of the element. //! Writes attributes of the element.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
...@@ -104,6 +115,7 @@ namespace gui ...@@ -104,6 +115,7 @@ namespace gui
bool WordWrap; bool WordWrap;
bool Background; bool Background;
bool RestrainTextInside; bool RestrainTextInside;
bool RightToLeft;
video::SColor OverrideColor, BGColor; video::SColor OverrideColor, BGColor;
gui::IGUIFont* OverrideFont; gui::IGUIFont* OverrideFont;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment