123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621 |
- // Copyright (C) 2002-2012 Nikolaus Gebhardt
- // This file is part of the "Irrlicht Engine".
- // For conditions of distribution and use, see copyright notice in irrlicht.h
- #include "CGUIStaticText.h"
- #ifdef _IRR_COMPILE_WITH_GUI_
- #include "IGUISkin.h"
- #include "IGUIEnvironment.h"
- #include "IGUIFont.h"
- #include "IVideoDriver.h"
- #include "rect.h"
- #include "utfwrapping.h"
- namespace irr
- {
- namespace gui
- {
- //! constructor
- CGUIStaticText::CGUIStaticText(const wchar_t* text, bool border,
- IGUIEnvironment* environment, IGUIElement* parent,
- s32 id, const core::rect<s32>& rectangle,
- bool background)
- : IGUIStaticText(environment, parent, id, rectangle),
- HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT),
- Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background),
- RestrainTextInside(true), RightToLeft(false),
- OverrideColor(video::SColor(101,255,255,255)), BGColor(video::SColor(101,210,210,210)),
- OverrideFont(0), LastBreakFont(0)
- {
- #ifdef _DEBUG
- setDebugName("CGUIStaticText");
- #endif
- Text = text;
- if (environment && environment->getSkin())
- {
- BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE);
- }
- }
- //! destructor
- CGUIStaticText::~CGUIStaticText()
- {
- if (OverrideFont)
- OverrideFont->drop();
- }
- //! draws the element and its children
- void CGUIStaticText::draw()
- {
- if (!IsVisible)
- return;
- IGUISkin* skin = Environment->getSkin();
- if (!skin)
- return;
- video::IVideoDriver* driver = Environment->getVideoDriver();
- core::rect<s32> frameRect(AbsoluteRect);
- // draw background
- if (Background)
- {
- if ( !OverrideBGColorEnabled ) // skin-colors can change
- BGColor = skin->getColor(gui::EGDC_3D_FACE);
- driver->draw2DRectangle(BGColor, frameRect, &AbsoluteClippingRect);
- }
- // draw the border
- if (Border)
- {
- skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect);
- frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
- }
- // draw the text
- if (Text.size())
- {
- IGUIFont* font = getActiveFont();
- if (font)
- {
- if (!WordWrap)
- {
- if (VAlign == EGUIA_LOWERRIGHT)
- {
- frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y -
- font->getDimension(L"A").Height - font->getKerningHeight();
- }
- if (HAlign == EGUIA_LOWERRIGHT)
- {
- frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
- font->getDimension(Text.c_str()).Width;
- }
- font->draw(Text.c_str(), frameRect,
- OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
- HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
- }
- else
- {
- if (font != LastBreakFont)
- breakText();
- core::rect<s32> r = frameRect;
- s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
- s32 totalHeight = height * BrokenText.size();
- if (VAlign == EGUIA_CENTER)
- {
- r.UpperLeftCorner.Y = r.getCenter().Y - (totalHeight / 2);
- }
- else if (VAlign == EGUIA_LOWERRIGHT)
- {
- r.UpperLeftCorner.Y = r.LowerRightCorner.Y - totalHeight;
- }
- for (u32 i=0; i<BrokenText.size(); ++i)
- {
- if (HAlign == EGUIA_LOWERRIGHT)
- {
- r.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
- font->getDimension(BrokenText[i].c_str()).Width;
- }
- font->draw(BrokenText[i].c_str(), r,
- OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
- HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
- r.LowerRightCorner.Y += height;
- r.UpperLeftCorner.Y += height;
- }
- }
- }
- }
- IGUIElement::draw();
- }
- //! Sets another skin independent font.
- void CGUIStaticText::setOverrideFont(IGUIFont* font)
- {
- if (OverrideFont == font)
- return;
- if (OverrideFont)
- OverrideFont->drop();
- OverrideFont = font;
- if (OverrideFont)
- OverrideFont->grab();
- breakText();
- }
- //! Gets the override font (if any)
- IGUIFont * CGUIStaticText::getOverrideFont() const
- {
- return OverrideFont;
- }
- //! Get the font which is used right now for drawing
- IGUIFont* CGUIStaticText::getActiveFont() const
- {
- if ( OverrideFont )
- return OverrideFont;
- IGUISkin* skin = Environment->getSkin();
- if (skin)
- return skin->getFont();
- return 0;
- }
- //! Sets another color for the text.
- void CGUIStaticText::setOverrideColor(video::SColor color)
- {
- OverrideColor = color;
- OverrideColorEnabled = true;
- }
- //! Sets another color for the text.
- void CGUIStaticText::setBackgroundColor(video::SColor color)
- {
- BGColor = color;
- OverrideBGColorEnabled = true;
- Background = true;
- }
- //! Sets whether to draw the background
- void CGUIStaticText::setDrawBackground(bool draw)
- {
- Background = draw;
- }
- //! Gets the background color
- video::SColor CGUIStaticText::getBackgroundColor() const
- {
- return BGColor;
- }
- //! Checks if background drawing is enabled
- bool CGUIStaticText::isDrawBackgroundEnabled() const
- {
- _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
- return Background;
- }
- //! Sets whether to draw the border
- void CGUIStaticText::setDrawBorder(bool draw)
- {
- Border = draw;
- }
- //! Checks if border drawing is enabled
- bool CGUIStaticText::isDrawBorderEnabled() const
- {
- _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
- return Border;
- }
- void CGUIStaticText::setTextRestrainedInside(bool restrainTextInside)
- {
- RestrainTextInside = restrainTextInside;
- }
- bool CGUIStaticText::isTextRestrainedInside() const
- {
- return RestrainTextInside;
- }
- void CGUIStaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
- {
- HAlign = horizontal;
- VAlign = vertical;
- }
- video::SColor CGUIStaticText::getOverrideColor() const
- {
- return OverrideColor;
- }
- //! Sets if the static text should use the overide color or the
- //! color in the gui skin.
- void CGUIStaticText::enableOverrideColor(bool enable)
- {
- OverrideColorEnabled = enable;
- }
- bool CGUIStaticText::isOverrideColorEnabled() const
- {
- _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
- return OverrideColorEnabled;
- }
- //! Enables or disables word wrap for using the static text as
- //! multiline text control.
- void CGUIStaticText::setWordWrap(bool enable)
- {
- WordWrap = enable;
- breakText();
- }
- bool CGUIStaticText::isWordWrapEnabled() const
- {
- _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
- return WordWrap;
- }
- void CGUIStaticText::setRightToLeft(bool rtl)
- {
- if (RightToLeft != rtl)
- {
- RightToLeft = rtl;
- breakText();
- }
- }
- bool CGUIStaticText::isRightToLeft() const
- {
- return RightToLeft;
- }
- //! Breaks the single text line.
- void CGUIStaticText::breakText()
- {
- if (!WordWrap)
- return;
- BrokenText.clear();
- IGUISkin* skin = Environment->getSkin();
- IGUIFont* font = getActiveFont();
- if (!font)
- return;
- LastBreakFont = font;
- core::stringw line;
- core::stringw word;
- core::stringw whitespace;
- s32 size = Text.size();
- s32 length = 0;
- s32 elWidth = RelativeRect.getWidth();
- if (Border)
- elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
- wchar_t c;
- // We have to deal with right-to-left and left-to-right differently
- // However, most parts of the following code is the same, it's just
- // some order and boundaries which change.
- if (!RightToLeft)
- {
- // regular (left-to-right)
- for (s32 i=0; i<size; ++i)
- {
- c = Text[i];
- bool lineBreak = false;
- if (c == L'\r') // Mac or Windows breaks
- {
- lineBreak = true;
- if (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';
- }
- word += c;
- if (word.size())
- {
- const s32 wordlgth = font->getDimension(word.c_str()).Width;
- if (length && (length + wordlgth > elWidth))
- { // too long to fit inside
- // break to next line
- unsigned int where = 1;
- while (where != line.size()) //Find the first breakable position
- {
- if (UtfNoEnding(Text[i - where]) || //Prevent unsuitable character from displaying
- UtfNoStarting(Text[i - where]) || //at the position of starting or ending of a line
- UtfNoStarting(Text[i + 1 - where])) //Handle case which more than one non-newline-starting characters are together
- {
- where++;
- continue;
- }
- if (breakable(Text[i - where]))
- break;
- else
- where++;
- }
- if (where != line.size())
- {
- core::stringw first = line.subString(0, line.size() + 1 - where);
- core::stringw second = line.subString(line.size() + 1 - where , where - 1);
- if (first.lastChar() == wchar_t(0x00AD))
- BrokenText.push_back(first + L"-"); //Print the Unicode Soft HYphen (SHY / 00AD) character
- else
- BrokenText.push_back(first);
- const s32 secondLength = font->getDimension(second.c_str()).Width;
- length = secondLength + wordlgth;
- line = second + word;
- }
- else if (breakable(c) || UtfNoEnding(c) || UtfNoStarting(c)) //Unusual case
- {
- BrokenText.push_back(line); //Force breaking to next line too if last word is breakable,
- line = word; //it happens when someone writes too many non-newline-starting
- length = wordlgth; //chars in the first line, so we ignore the rules.
- }
- // No suitable place to break words, so there's nothing more we can do
- // break to next line
- else
- {
- line += word;
- length += wordlgth;
- }
- }
- else
- {
- line += word;
- length += wordlgth;
- }
- word = L"";
- }
- // compute line break
- if (lineBreak)
- {
- line += word;
- BrokenText.push_back(line);
- line = L"";
- word = L"";
- length = 0;
- }
- }
- line += word;
- BrokenText.push_back(line);
- }
- else
- {
- // right-to-left
- for (s32 i=size; i>=0; --i)
- {
- c = Text[i];
- bool lineBreak = false;
- if (c == L'\r') // Mac or Windows breaks
- {
- 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';
- }
- 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;
- }
- word = L"";
- whitespace = L"";
- }
- if (c != 0)
- 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
- {
- // yippee this is a word..
- word = core::stringw(&c, 1) + word;
- }
- }
- line = whitespace + line;
- line = word + line;
- BrokenText.push_back(line);
- }
- }
- //! Sets the new caption of this element.
- void CGUIStaticText::setText(const wchar_t* text)
- {
- IGUIElement::setText(text);
- breakText();
- }
- void CGUIStaticText::updateAbsolutePosition()
- {
- IGUIElement::updateAbsolutePosition();
- breakText();
- }
- //! Returns the height of the text in pixels when it is drawn.
- s32 CGUIStaticText::getTextHeight() const
- {
- IGUIFont* font = getActiveFont();
- if (!font)
- return 0;
- s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
- if (WordWrap)
- height *= BrokenText.size();
- return height;
- }
- s32 CGUIStaticText::getTextWidth() const
- {
- IGUIFont * font = getActiveFont();
- if(!font)
- return 0;
- if(WordWrap)
- {
- s32 widest = 0;
- for(u32 line = 0; line < BrokenText.size(); ++line)
- {
- s32 width = font->getDimension(BrokenText[line].c_str()).Width;
- if(width > widest)
- widest = width;
- }
- return widest;
- }
- else
- {
- return font->getDimension(Text.c_str()).Width;
- }
- }
- //! Writes attributes of the element.
- //! Implement this to expose the attributes of your element for
- //! scripting languages, editors, debuggers or xml serialization purposes.
- void CGUIStaticText::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
- {
- IGUIStaticText::serializeAttributes(out,options);
- out->addBool ("Border", Border);
- out->addBool ("OverrideColorEnabled",OverrideColorEnabled);
- out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled);
- out->addBool ("WordWrap", WordWrap);
- out->addBool ("Background", Background);
- out->addBool ("RightToLeft", RightToLeft);
- out->addBool ("RestrainTextInside", RestrainTextInside);
- out->addColor ("OverrideColor", OverrideColor);
- out->addColor ("BGColor", BGColor);
- out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
- out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
- // out->addFont ("OverrideFont", OverrideFont);
- }
- //! Reads attributes of the element
- void CGUIStaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
- {
- IGUIStaticText::deserializeAttributes(in,options);
- Border = in->getAttributeAsBool("Border");
- enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
- OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled");
- setWordWrap(in->getAttributeAsBool("WordWrap"));
- Background = in->getAttributeAsBool("Background");
- RightToLeft = in->getAttributeAsBool("RightToLeft");
- RestrainTextInside = in->getAttributeAsBool("RestrainTextInside");
- OverrideColor = in->getAttributeAsColor("OverrideColor");
- BGColor = in->getAttributeAsColor("BGColor");
- setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
- (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
- // OverrideFont = in->getAttributeAsFont("OverrideFont");
- }
- } // end namespace gui
- } // end namespace irr
- #endif // _IRR_COMPILE_WITH_GUI_
|