1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // Copyright (C) 2016 Nathanaƫl Courant:
3 // Modified the functions to use EnrichedText instead of string.
4 // This file is part of the "Irrlicht Engine".
5 // For conditions of distribution and use, see copyright notice in irrlicht.h
7 #include "static_text.h"
8 #ifdef _IRR_COMPILE_WITH_GUI_
11 #include <IVideoDriver.h>
16 #include "CGUITTFont.h"
19 #include "util/string.h"
29 StaticText::StaticText(const EnrichedString &text, bool border,
30 IGUIEnvironment* environment, IGUIElement* parent,
31 s32 id, const core::rect<s32>& rectangle,
33 : IGUIStaticText(environment, parent, id, rectangle),
34 HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT),
35 Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background),
36 RestrainTextInside(true), RightToLeft(false),
37 OverrideColor(video::SColor(101,255,255,255)), BGColor(video::SColor(101,210,210,210)),
38 OverrideFont(0), LastBreakFont(0)
41 setDebugName("StaticText");
46 if (environment && environment->getSkin())
48 BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE);
54 StaticText::~StaticText()
60 //! draws the element and its children
61 void StaticText::draw()
66 IGUISkin* skin = Environment->getSkin();
69 video::IVideoDriver* driver = Environment->getVideoDriver();
71 core::rect<s32> frameRect(AbsoluteRect);
77 if ( !OverrideBGColorEnabled ) // skin-colors can change
78 BGColor = skin->getColor(gui::EGDC_3D_FACE);
80 driver->draw2DRectangle(BGColor, frameRect, &AbsoluteClippingRect);
87 skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect);
88 frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
94 IGUIFont* font = getActiveFont();
100 // TODO: add colors here
101 if (VAlign == EGUIA_LOWERRIGHT)
103 frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y -
104 font->getDimension(L"A").Height - font->getKerningHeight();
106 if (HAlign == EGUIA_LOWERRIGHT)
108 frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
109 font->getDimension(cText.c_str()).Width;
113 if (font->getType() == irr::gui::EGFT_CUSTOM) {
114 irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
115 tmp->draw(Text, frameRect,
116 OverrideColorEnabled ? OverrideColor :
117 skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
118 HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER,
119 (RestrainTextInside ? &AbsoluteClippingRect : NULL));
123 font->draw(Text.c_str(), frameRect,
124 skin->getColor(EGDC_BUTTON_TEXT),
125 HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER,
126 (RestrainTextInside ? &AbsoluteClippingRect : NULL));
131 if (font != LastBreakFont)
134 core::rect<s32> r = frameRect;
135 s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
136 s32 totalHeight = height * BrokenText.size();
137 if (VAlign == EGUIA_CENTER)
139 r.UpperLeftCorner.Y = r.getCenter().Y - (totalHeight / 2);
141 else if (VAlign == EGUIA_LOWERRIGHT)
143 r.UpperLeftCorner.Y = r.LowerRightCorner.Y - totalHeight;
146 irr::video::SColor previous_color(255, 255, 255, 255);
147 for (u32 i=0; i<BrokenText.size(); ++i)
149 if (HAlign == EGUIA_LOWERRIGHT)
151 r.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
152 font->getDimension(BrokenText[i].c_str()).Width;
155 EnrichedString str = BrokenText[i];
157 //str = colorizeText(BrokenText[i].c_str(), colors, previous_color);
158 //if (!colors.empty())
159 // previous_color = colors[colors.size() - 1];
162 if (font->getType() == irr::gui::EGFT_CUSTOM) {
163 irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
165 r, previous_color, // FIXME
166 HAlign == EGUIA_CENTER, false,
167 (RestrainTextInside ? &AbsoluteClippingRect : NULL));
171 // Draw non-colored text
172 font->draw(str.c_str(),
173 r, skin->getColor(EGDC_BUTTON_TEXT),
174 HAlign == EGUIA_CENTER, false,
175 (RestrainTextInside ? &AbsoluteClippingRect : NULL));
179 r.LowerRightCorner.Y += height;
180 r.UpperLeftCorner.Y += height;
190 //! Sets another skin independent font.
191 void StaticText::setOverrideFont(IGUIFont* font)
193 if (OverrideFont == font)
197 OverrideFont->drop();
202 OverrideFont->grab();
207 //! Gets the override font (if any)
208 IGUIFont * StaticText::getOverrideFont() const
213 //! Get the font which is used right now for drawing
214 IGUIFont* StaticText::getActiveFont() const
218 IGUISkin* skin = Environment->getSkin();
220 return skin->getFont();
224 //! Sets another color for the text.
225 void StaticText::setOverrideColor(video::SColor color)
227 OverrideColor = color;
228 OverrideColorEnabled = true;
232 //! Sets another color for the text.
233 void StaticText::setBackgroundColor(video::SColor color)
236 OverrideBGColorEnabled = true;
241 //! Sets whether to draw the background
242 void StaticText::setDrawBackground(bool draw)
248 //! Gets the background color
249 video::SColor StaticText::getBackgroundColor() const
255 //! Checks if background drawing is enabled
256 bool StaticText::isDrawBackgroundEnabled() const
262 //! Sets whether to draw the border
263 void StaticText::setDrawBorder(bool draw)
269 //! Checks if border drawing is enabled
270 bool StaticText::isDrawBorderEnabled() const
276 void StaticText::setTextRestrainedInside(bool restrainTextInside)
278 RestrainTextInside = restrainTextInside;
282 bool StaticText::isTextRestrainedInside() const
284 return RestrainTextInside;
288 void StaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
295 #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7
296 const video::SColor& StaticText::getOverrideColor() const
298 video::SColor StaticText::getOverrideColor() const
301 return OverrideColor;
305 //! Sets if the static text should use the overide color or the
306 //! color in the gui skin.
307 void StaticText::enableOverrideColor(bool enable)
309 OverrideColorEnabled = enable;
313 bool StaticText::isOverrideColorEnabled() const
315 return OverrideColorEnabled;
319 //! Enables or disables word wrap for using the static text as
320 //! multiline text control.
321 void StaticText::setWordWrap(bool enable)
328 bool StaticText::isWordWrapEnabled() const
334 void StaticText::setRightToLeft(bool rtl)
336 if (RightToLeft != rtl)
344 bool StaticText::isRightToLeft() const
350 //! Breaks the single text line.
351 void StaticText::breakText()
358 IGUISkin* skin = Environment->getSkin();
359 IGUIFont* font = getActiveFont();
363 LastBreakFont = font;
367 EnrichedString whitespace;
368 s32 size = cText.size();
370 s32 elWidth = RelativeRect.getWidth();
372 elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
375 //std::vector<irr::video::SColor> colors;
377 // We have to deal with right-to-left and left-to-right differently
378 // However, most parts of the following code is the same, it's just
379 // some order and boundaries which change.
382 // regular (left-to-right)
383 for (s32 i=0; i<size; ++i)
385 c = cText.getString()[i];
386 bool lineBreak = false;
388 if (c == L'\r') // Mac or Windows breaks
391 //if (Text[i+1] == L'\n') // Windows breaks
398 else if (c == L'\n') // Unix breaks
404 bool isWhitespace = (c == L' ' || c == 0);
409 word.addChar(cText, i);
412 if ( isWhitespace || i == (size-1))
416 // here comes the next whitespace, look if
417 // we must break the last word to the next line.
418 const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
419 //const std::wstring sanitized = removeEscapes(word.c_str());
420 const s32 wordlgth = font->getDimension(word.c_str()).Width;
422 if (wordlgth > elWidth)
424 // This word is too long to fit in the available space, look for
425 // the Unicode Soft HYphen (SHY / 00AD) character for a place to
427 int where = core::stringw(word.c_str()).findFirst( wchar_t(0x00AD) );
430 EnrichedString first = word.substr(0, where);
431 EnrichedString second = word.substr(where, word.size() - where);
432 first.addCharNoColor(L'-');
433 BrokenText.push_back(line + first);
434 const s32 secondLength = font->getDimension(second.c_str()).Width;
436 length = secondLength;
441 // No soft hyphen found, so there's nothing more we can do
442 // break to next line
444 BrokenText.push_back(line);
449 else if (length && (length + wordlgth + whitelgth > elWidth))
451 // break to next line
452 BrokenText.push_back(line);
461 length += whitelgth + wordlgth;
468 if ( isWhitespace && c != 0)
470 whitespace.addChar(cText, i);
473 // compute line break
478 BrokenText.push_back(line);
489 BrokenText.push_back(line);
494 for (s32 i=size; i>=0; --i)
496 c = cText.getString()[i];
497 bool lineBreak = false;
499 if (c == L'\r') // Mac or Windows breaks
502 //if ((i>0) && Text[i-1] == L'\n') // Windows breaks
509 else if (c == L'\n') // Unix breaks
515 if (c==L' ' || c==0 || i==0)
519 // here comes the next whitespace, look if
520 // we must break the last word to the next line.
521 const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
522 const s32 wordlgth = font->getDimension(word.c_str()).Width;
524 if (length && (length + wordlgth + whitelgth > elWidth))
526 // break to next line
527 BrokenText.push_back(line);
534 line = whitespace + line;
536 length += whitelgth + wordlgth;
544 // whitespace = core::stringw(&c, 1) + whitespace;
545 whitespace = cText.substr(i, 1) + whitespace;
547 // compute line break
550 line = whitespace + line;
552 BrokenText.push_back(line);
561 // yippee this is a word..
562 //word = core::stringw(&c, 1) + word;
563 word = cText.substr(i, 1) + word;
567 line = whitespace + line;
569 BrokenText.push_back(line);
574 //! Sets the new caption of this element.
575 void StaticText::setText(const wchar_t* text)
577 setText(EnrichedString(text));
580 //! Sets the new caption of this element.
581 void StaticText::setText(const EnrichedString &text)
583 IGUIElement::setText(text.c_str());
585 if (text.hasBackground()) {
586 setBackgroundColor(text.getBackground());
592 void StaticText::updateAbsolutePosition()
594 IGUIElement::updateAbsolutePosition();
599 //! Returns the height of the text in pixels when it is drawn.
600 s32 StaticText::getTextHeight() const
602 IGUIFont* font = getActiveFont();
606 s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
609 height *= BrokenText.size();
615 s32 StaticText::getTextWidth() const
617 IGUIFont * font = getActiveFont();
625 for(u32 line = 0; line < BrokenText.size(); ++line)
627 s32 width = font->getDimension(BrokenText[line].c_str()).Width;
637 return font->getDimension(cText.c_str()).Width;
642 //! Writes attributes of the element.
643 //! Implement this to expose the attributes of your element for
644 //! scripting languages, editors, debuggers or xml serialization purposes.
645 void StaticText::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
647 IGUIStaticText::serializeAttributes(out,options);
649 out->addBool ("Border", Border);
650 out->addBool ("OverrideColorEnabled",OverrideColorEnabled);
651 out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled);
652 out->addBool ("WordWrap", WordWrap);
653 out->addBool ("Background", Background);
654 out->addBool ("RightToLeft", RightToLeft);
655 out->addBool ("RestrainTextInside", RestrainTextInside);
656 out->addColor ("OverrideColor", OverrideColor);
657 out->addColor ("BGColor", BGColor);
658 out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
659 out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
661 // out->addFont ("OverrideFont", OverrideFont);
665 //! Reads attributes of the element
666 void StaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
668 IGUIStaticText::deserializeAttributes(in,options);
670 Border = in->getAttributeAsBool("Border");
671 enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
672 OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled");
673 setWordWrap(in->getAttributeAsBool("WordWrap"));
674 Background = in->getAttributeAsBool("Background");
675 RightToLeft = in->getAttributeAsBool("RightToLeft");
676 RestrainTextInside = in->getAttributeAsBool("RestrainTextInside");
677 OverrideColor = in->getAttributeAsColor("OverrideColor");
678 BGColor = in->getAttributeAsColor("BGColor");
680 setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
681 (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
683 // OverrideFont = in->getAttributeAsFont("OverrideFont");
686 } // end namespace gui
688 #endif // USE_FREETYPE
690 } // end namespace irr
693 #endif // _IRR_COMPILE_WITH_GUI_