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_
14 #include <IGUIEnvironment.h>
16 #include <IVideoDriver.h>
21 #include "cguittfont/xCGUITTFont.h"
24 #include "util/string.h"
34 StaticText::StaticText(const EnrichedString &text, bool border,
35 IGUIEnvironment* environment, IGUIElement* parent,
36 s32 id, const core::rect<s32>& rectangle,
38 : IGUIStaticText(environment, parent, id, rectangle),
39 HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT),
40 Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background),
41 RestrainTextInside(true), RightToLeft(false),
42 OverrideColor(video::SColor(101,255,255,255)), BGColor(video::SColor(101,210,210,210)),
43 OverrideFont(0), LastBreakFont(0)
46 setDebugName("StaticText");
51 if (environment && environment->getSkin())
53 BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE);
59 StaticText::~StaticText()
65 //! draws the element and its children
66 void StaticText::draw()
71 IGUISkin* skin = Environment->getSkin();
74 video::IVideoDriver* driver = Environment->getVideoDriver();
76 core::rect<s32> frameRect(AbsoluteRect);
82 if ( !OverrideBGColorEnabled ) // skin-colors can change
83 BGColor = skin->getColor(gui::EGDC_3D_FACE);
85 driver->draw2DRectangle(BGColor, frameRect, &AbsoluteClippingRect);
92 skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect);
93 frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
99 IGUIFont* font = getActiveFont();
105 // TODO: add colors here
106 if (VAlign == EGUIA_LOWERRIGHT)
108 frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y -
109 font->getDimension(L"A").Height - font->getKerningHeight();
111 if (HAlign == EGUIA_LOWERRIGHT)
113 frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
114 font->getDimension(cText.c_str()).Width;
117 irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
118 tmp->draw(cText, frameRect,
119 OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
120 HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
124 if (font != LastBreakFont)
127 core::rect<s32> r = frameRect;
128 s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
129 s32 totalHeight = height * BrokenText.size();
130 if (VAlign == EGUIA_CENTER)
132 r.UpperLeftCorner.Y = r.getCenter().Y - (totalHeight / 2);
134 else if (VAlign == EGUIA_LOWERRIGHT)
136 r.UpperLeftCorner.Y = r.LowerRightCorner.Y - totalHeight;
139 irr::video::SColor previous_color(255, 255, 255, 255);
140 for (u32 i=0; i<BrokenText.size(); ++i)
142 if (HAlign == EGUIA_LOWERRIGHT)
144 r.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
145 font->getDimension(BrokenText[i].c_str()).Width;
148 //std::vector<irr::video::SColor> colors;
150 EnrichedString str = BrokenText[i];
152 //str = colorizeText(BrokenText[i].c_str(), colors, previous_color);
153 //if (!colors.empty())
154 // previous_color = colors[colors.size() - 1];
156 irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
158 previous_color, // FIXME
159 HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
161 r.LowerRightCorner.Y += height;
162 r.UpperLeftCorner.Y += height;
172 //! Sets another skin independent font.
173 void StaticText::setOverrideFont(IGUIFont* font)
175 if (OverrideFont == font)
179 OverrideFont->drop();
184 OverrideFont->grab();
189 //! Gets the override font (if any)
190 IGUIFont * StaticText::getOverrideFont() const
195 //! Get the font which is used right now for drawing
196 IGUIFont* StaticText::getActiveFont() const
200 IGUISkin* skin = Environment->getSkin();
202 return skin->getFont();
206 //! Sets another color for the text.
207 void StaticText::setOverrideColor(video::SColor color)
209 OverrideColor = color;
210 OverrideColorEnabled = true;
214 //! Sets another color for the text.
215 void StaticText::setBackgroundColor(video::SColor color)
218 OverrideBGColorEnabled = true;
223 //! Sets whether to draw the background
224 void StaticText::setDrawBackground(bool draw)
230 //! Gets the background color
231 video::SColor StaticText::getBackgroundColor() const
237 //! Checks if background drawing is enabled
238 bool StaticText::isDrawBackgroundEnabled() const
240 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
245 //! Sets whether to draw the border
246 void StaticText::setDrawBorder(bool draw)
252 //! Checks if border drawing is enabled
253 bool StaticText::isDrawBorderEnabled() const
255 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
260 void StaticText::setTextRestrainedInside(bool restrainTextInside)
262 RestrainTextInside = restrainTextInside;
266 bool StaticText::isTextRestrainedInside() const
268 return RestrainTextInside;
272 void StaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
279 #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7
280 const video::SColor& StaticText::getOverrideColor() const
282 video::SColor StaticText::getOverrideColor() const
285 return OverrideColor;
289 //! Sets if the static text should use the overide color or the
290 //! color in the gui skin.
291 void StaticText::enableOverrideColor(bool enable)
293 OverrideColorEnabled = enable;
297 bool StaticText::isOverrideColorEnabled() const
299 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
300 return OverrideColorEnabled;
304 //! Enables or disables word wrap for using the static text as
305 //! multiline text control.
306 void StaticText::setWordWrap(bool enable)
313 bool StaticText::isWordWrapEnabled() const
315 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
320 void StaticText::setRightToLeft(bool rtl)
322 if (RightToLeft != rtl)
330 bool StaticText::isRightToLeft() const
336 //! Breaks the single text line.
337 void StaticText::breakText()
344 IGUISkin* skin = Environment->getSkin();
345 IGUIFont* font = getActiveFont();
349 LastBreakFont = font;
353 EnrichedString whitespace;
354 s32 size = cText.size();
356 s32 elWidth = RelativeRect.getWidth();
358 elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
361 //std::vector<irr::video::SColor> colors;
363 // We have to deal with right-to-left and left-to-right differently
364 // However, most parts of the following code is the same, it's just
365 // some order and boundaries which change.
368 // regular (left-to-right)
369 for (s32 i=0; i<size; ++i)
371 c = cText.getString()[i];
372 bool lineBreak = false;
374 if (c == L'\r') // Mac or Windows breaks
377 //if (Text[i+1] == L'\n') // Windows breaks
384 else if (c == L'\n') // Unix breaks
390 bool isWhitespace = (c == L' ' || c == 0);
395 word.addChar(cText, i);
398 if ( isWhitespace || i == (size-1))
402 // here comes the next whitespace, look if
403 // we must break the last word to the next line.
404 const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
405 //const std::wstring sanitized = removeEscapes(word.c_str());
406 const s32 wordlgth = font->getDimension(word.c_str()).Width;
408 if (wordlgth > elWidth)
410 // This word is too long to fit in the available space, look for
411 // the Unicode Soft HYphen (SHY / 00AD) character for a place to
413 int where = core::stringw(word.c_str()).findFirst( wchar_t(0x00AD) );
416 EnrichedString first = word.substr(0, where);
417 EnrichedString second = word.substr(where, word.size() - where);
418 first.addCharNoColor(L'-');
419 BrokenText.push_back(line + first);
420 const s32 secondLength = font->getDimension(second.c_str()).Width;
422 length = secondLength;
427 // No soft hyphen found, so there's nothing more we can do
428 // break to next line
430 BrokenText.push_back(line);
435 else if (length && (length + wordlgth + whitelgth > elWidth))
437 // break to next line
438 BrokenText.push_back(line);
447 length += whitelgth + wordlgth;
454 if ( isWhitespace && c != 0)
456 whitespace.addChar(cText, i);
459 // compute line break
464 BrokenText.push_back(line);
475 BrokenText.push_back(line);
480 for (s32 i=size; i>=0; --i)
482 c = cText.getString()[i];
483 bool lineBreak = false;
485 if (c == L'\r') // Mac or Windows breaks
488 //if ((i>0) && Text[i-1] == L'\n') // Windows breaks
495 else if (c == L'\n') // Unix breaks
501 if (c==L' ' || c==0 || i==0)
505 // here comes the next whitespace, look if
506 // we must break the last word to the next line.
507 const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
508 const s32 wordlgth = font->getDimension(word.c_str()).Width;
510 if (length && (length + wordlgth + whitelgth > elWidth))
512 // break to next line
513 BrokenText.push_back(line);
520 line = whitespace + line;
522 length += whitelgth + wordlgth;
530 // whitespace = core::stringw(&c, 1) + whitespace;
531 whitespace = cText.substr(i, 1) + whitespace;
533 // compute line break
536 line = whitespace + line;
538 BrokenText.push_back(line);
547 // yippee this is a word..
548 //word = core::stringw(&c, 1) + word;
549 word = cText.substr(i, 1) + word;
553 line = whitespace + line;
555 BrokenText.push_back(line);
560 //! Sets the new caption of this element.
561 void StaticText::setText(const wchar_t* text)
563 setText(EnrichedString(text));
566 //! Sets the new caption of this element.
567 void StaticText::setText(const EnrichedString &text)
569 IGUIElement::setText(text.c_str());
571 if (text.hasBackground()) {
572 setBackgroundColor(text.getBackground());
578 void StaticText::updateAbsolutePosition()
580 IGUIElement::updateAbsolutePosition();
585 //! Returns the height of the text in pixels when it is drawn.
586 s32 StaticText::getTextHeight() const
588 IGUIFont* font = getActiveFont();
592 s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
595 height *= BrokenText.size();
601 s32 StaticText::getTextWidth() const
603 IGUIFont * font = getActiveFont();
611 for(u32 line = 0; line < BrokenText.size(); ++line)
613 s32 width = font->getDimension(BrokenText[line].c_str()).Width;
623 return font->getDimension(cText.c_str()).Width;
628 //! Writes attributes of the element.
629 //! Implement this to expose the attributes of your element for
630 //! scripting languages, editors, debuggers or xml serialization purposes.
631 void StaticText::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
633 IGUIStaticText::serializeAttributes(out,options);
635 out->addBool ("Border", Border);
636 out->addBool ("OverrideColorEnabled",OverrideColorEnabled);
637 out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled);
638 out->addBool ("WordWrap", WordWrap);
639 out->addBool ("Background", Background);
640 out->addBool ("RightToLeft", RightToLeft);
641 out->addBool ("RestrainTextInside", RestrainTextInside);
642 out->addColor ("OverrideColor", OverrideColor);
643 out->addColor ("BGColor", BGColor);
644 out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
645 out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
647 // out->addFont ("OverrideFont", OverrideFont);
651 //! Reads attributes of the element
652 void StaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
654 IGUIStaticText::deserializeAttributes(in,options);
656 Border = in->getAttributeAsBool("Border");
657 enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
658 OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled");
659 setWordWrap(in->getAttributeAsBool("WordWrap"));
660 Background = in->getAttributeAsBool("Background");
661 RightToLeft = in->getAttributeAsBool("RightToLeft");
662 RestrainTextInside = in->getAttributeAsBool("RestrainTextInside");
663 OverrideColor = in->getAttributeAsColor("OverrideColor");
664 BGColor = in->getAttributeAsColor("BGColor");
666 setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
667 (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
669 // OverrideFont = in->getAttributeAsFont("OverrideFont");
672 } // end namespace gui
674 #endif // USE_FREETYPE
676 } // end namespace irr
679 #endif // _IRR_COMPILE_WITH_GUI_