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"
18 #ifndef _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX
19 // newer Irrlicht versions no longer have this
20 #define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX
23 #include "util/string.h"
33 StaticText::StaticText(const EnrichedString &text, bool border,
34 IGUIEnvironment* environment, IGUIElement* parent,
35 s32 id, const core::rect<s32>& rectangle,
37 : IGUIStaticText(environment, parent, id, rectangle),
38 HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT),
39 Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background),
40 RestrainTextInside(true), RightToLeft(false),
41 OverrideColor(video::SColor(101,255,255,255)), BGColor(video::SColor(101,210,210,210)),
42 OverrideFont(0), LastBreakFont(0)
45 setDebugName("StaticText");
50 if (environment && environment->getSkin())
52 BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE);
58 StaticText::~StaticText()
64 //! draws the element and its children
65 void StaticText::draw()
70 IGUISkin* skin = Environment->getSkin();
73 video::IVideoDriver* driver = Environment->getVideoDriver();
75 core::rect<s32> frameRect(AbsoluteRect);
81 if ( !OverrideBGColorEnabled ) // skin-colors can change
82 BGColor = skin->getColor(gui::EGDC_3D_FACE);
84 driver->draw2DRectangle(BGColor, frameRect, &AbsoluteClippingRect);
91 skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect);
92 frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
98 IGUIFont* font = getActiveFont();
104 // TODO: add colors here
105 if (VAlign == EGUIA_LOWERRIGHT)
107 frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y -
108 font->getDimension(L"A").Height - font->getKerningHeight();
110 if (HAlign == EGUIA_LOWERRIGHT)
112 frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
113 font->getDimension(cText.c_str()).Width;
116 irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
117 tmp->draw(cText, frameRect,
118 OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
119 HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
123 if (font != LastBreakFont)
126 core::rect<s32> r = frameRect;
127 s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
128 s32 totalHeight = height * BrokenText.size();
129 if (VAlign == EGUIA_CENTER)
131 r.UpperLeftCorner.Y = r.getCenter().Y - (totalHeight / 2);
133 else if (VAlign == EGUIA_LOWERRIGHT)
135 r.UpperLeftCorner.Y = r.LowerRightCorner.Y - totalHeight;
138 irr::video::SColor previous_color(255, 255, 255, 255);
139 for (u32 i=0; i<BrokenText.size(); ++i)
141 if (HAlign == EGUIA_LOWERRIGHT)
143 r.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
144 font->getDimension(BrokenText[i].c_str()).Width;
147 //std::vector<irr::video::SColor> colors;
149 EnrichedString str = BrokenText[i];
151 //str = colorizeText(BrokenText[i].c_str(), colors, previous_color);
152 //if (!colors.empty())
153 // previous_color = colors[colors.size() - 1];
155 irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
157 previous_color, // FIXME
158 HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
160 r.LowerRightCorner.Y += height;
161 r.UpperLeftCorner.Y += height;
171 //! Sets another skin independent font.
172 void StaticText::setOverrideFont(IGUIFont* font)
174 if (OverrideFont == font)
178 OverrideFont->drop();
183 OverrideFont->grab();
188 //! Gets the override font (if any)
189 IGUIFont * StaticText::getOverrideFont() const
194 //! Get the font which is used right now for drawing
195 IGUIFont* StaticText::getActiveFont() const
199 IGUISkin* skin = Environment->getSkin();
201 return skin->getFont();
205 //! Sets another color for the text.
206 void StaticText::setOverrideColor(video::SColor color)
208 OverrideColor = color;
209 OverrideColorEnabled = true;
213 //! Sets another color for the text.
214 void StaticText::setBackgroundColor(video::SColor color)
217 OverrideBGColorEnabled = true;
222 //! Sets whether to draw the background
223 void StaticText::setDrawBackground(bool draw)
229 //! Gets the background color
230 video::SColor StaticText::getBackgroundColor() const
236 //! Checks if background drawing is enabled
237 bool StaticText::isDrawBackgroundEnabled() const
239 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
244 //! Sets whether to draw the border
245 void StaticText::setDrawBorder(bool draw)
251 //! Checks if border drawing is enabled
252 bool StaticText::isDrawBorderEnabled() const
254 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
259 void StaticText::setTextRestrainedInside(bool restrainTextInside)
261 RestrainTextInside = restrainTextInside;
265 bool StaticText::isTextRestrainedInside() const
267 return RestrainTextInside;
271 void StaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
278 #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7
279 const video::SColor& StaticText::getOverrideColor() const
281 video::SColor StaticText::getOverrideColor() const
284 return OverrideColor;
288 //! Sets if the static text should use the overide color or the
289 //! color in the gui skin.
290 void StaticText::enableOverrideColor(bool enable)
292 OverrideColorEnabled = enable;
296 bool StaticText::isOverrideColorEnabled() const
298 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
299 return OverrideColorEnabled;
303 //! Enables or disables word wrap for using the static text as
304 //! multiline text control.
305 void StaticText::setWordWrap(bool enable)
312 bool StaticText::isWordWrapEnabled() const
314 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
319 void StaticText::setRightToLeft(bool rtl)
321 if (RightToLeft != rtl)
329 bool StaticText::isRightToLeft() const
335 //! Breaks the single text line.
336 void StaticText::breakText()
343 IGUISkin* skin = Environment->getSkin();
344 IGUIFont* font = getActiveFont();
348 LastBreakFont = font;
352 EnrichedString whitespace;
353 s32 size = cText.size();
355 s32 elWidth = RelativeRect.getWidth();
357 elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
360 //std::vector<irr::video::SColor> colors;
362 // We have to deal with right-to-left and left-to-right differently
363 // However, most parts of the following code is the same, it's just
364 // some order and boundaries which change.
367 // regular (left-to-right)
368 for (s32 i=0; i<size; ++i)
370 c = cText.getString()[i];
371 bool lineBreak = false;
373 if (c == L'\r') // Mac or Windows breaks
376 //if (Text[i+1] == L'\n') // Windows breaks
383 else if (c == L'\n') // Unix breaks
389 bool isWhitespace = (c == L' ' || c == 0);
394 word.addChar(cText, i);
397 if ( isWhitespace || i == (size-1))
401 // here comes the next whitespace, look if
402 // we must break the last word to the next line.
403 const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
404 //const std::wstring sanitized = removeEscapes(word.c_str());
405 const s32 wordlgth = font->getDimension(word.c_str()).Width;
407 if (wordlgth > elWidth)
409 // This word is too long to fit in the available space, look for
410 // the Unicode Soft HYphen (SHY / 00AD) character for a place to
412 int where = core::stringw(word.c_str()).findFirst( wchar_t(0x00AD) );
415 EnrichedString first = word.substr(0, where);
416 EnrichedString second = word.substr(where, word.size() - where);
417 first.addCharNoColor(L'-');
418 BrokenText.push_back(line + first);
419 const s32 secondLength = font->getDimension(second.c_str()).Width;
421 length = secondLength;
426 // No soft hyphen found, so there's nothing more we can do
427 // break to next line
429 BrokenText.push_back(line);
434 else if (length && (length + wordlgth + whitelgth > elWidth))
436 // break to next line
437 BrokenText.push_back(line);
446 length += whitelgth + wordlgth;
453 if ( isWhitespace && c != 0)
455 whitespace.addChar(cText, i);
458 // compute line break
463 BrokenText.push_back(line);
474 BrokenText.push_back(line);
479 for (s32 i=size; i>=0; --i)
481 c = cText.getString()[i];
482 bool lineBreak = false;
484 if (c == L'\r') // Mac or Windows breaks
487 //if ((i>0) && Text[i-1] == L'\n') // Windows breaks
494 else if (c == L'\n') // Unix breaks
500 if (c==L' ' || c==0 || i==0)
504 // here comes the next whitespace, look if
505 // we must break the last word to the next line.
506 const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
507 const s32 wordlgth = font->getDimension(word.c_str()).Width;
509 if (length && (length + wordlgth + whitelgth > elWidth))
511 // break to next line
512 BrokenText.push_back(line);
519 line = whitespace + line;
521 length += whitelgth + wordlgth;
529 // whitespace = core::stringw(&c, 1) + whitespace;
530 whitespace = cText.substr(i, 1) + whitespace;
532 // compute line break
535 line = whitespace + line;
537 BrokenText.push_back(line);
546 // yippee this is a word..
547 //word = core::stringw(&c, 1) + word;
548 word = cText.substr(i, 1) + word;
552 line = whitespace + line;
554 BrokenText.push_back(line);
559 //! Sets the new caption of this element.
560 void StaticText::setText(const wchar_t* text)
562 setText(EnrichedString(text));
565 //! Sets the new caption of this element.
566 void StaticText::setText(const EnrichedString &text)
568 IGUIElement::setText(text.c_str());
570 if (text.hasBackground()) {
571 setBackgroundColor(text.getBackground());
577 void StaticText::updateAbsolutePosition()
579 IGUIElement::updateAbsolutePosition();
584 //! Returns the height of the text in pixels when it is drawn.
585 s32 StaticText::getTextHeight() const
587 IGUIFont* font = getActiveFont();
591 s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
594 height *= BrokenText.size();
600 s32 StaticText::getTextWidth() const
602 IGUIFont * font = getActiveFont();
610 for(u32 line = 0; line < BrokenText.size(); ++line)
612 s32 width = font->getDimension(BrokenText[line].c_str()).Width;
622 return font->getDimension(cText.c_str()).Width;
627 //! Writes attributes of the element.
628 //! Implement this to expose the attributes of your element for
629 //! scripting languages, editors, debuggers or xml serialization purposes.
630 void StaticText::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
632 IGUIStaticText::serializeAttributes(out,options);
634 out->addBool ("Border", Border);
635 out->addBool ("OverrideColorEnabled",OverrideColorEnabled);
636 out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled);
637 out->addBool ("WordWrap", WordWrap);
638 out->addBool ("Background", Background);
639 out->addBool ("RightToLeft", RightToLeft);
640 out->addBool ("RestrainTextInside", RestrainTextInside);
641 out->addColor ("OverrideColor", OverrideColor);
642 out->addColor ("BGColor", BGColor);
643 out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
644 out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
646 // out->addFont ("OverrideFont", OverrideFont);
650 //! Reads attributes of the element
651 void StaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
653 IGUIStaticText::deserializeAttributes(in,options);
655 Border = in->getAttributeAsBool("Border");
656 enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
657 OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled");
658 setWordWrap(in->getAttributeAsBool("WordWrap"));
659 Background = in->getAttributeAsBool("Background");
660 RightToLeft = in->getAttributeAsBool("RightToLeft");
661 RestrainTextInside = in->getAttributeAsBool("RestrainTextInside");
662 OverrideColor = in->getAttributeAsColor("OverrideColor");
663 BGColor = in->getAttributeAsColor("BGColor");
665 setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
666 (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
668 // OverrideFont = in->getAttributeAsFont("OverrideFont");
671 } // end namespace gui
673 #endif // USE_FREETYPE
675 } // end namespace irr
678 #endif // _IRR_COMPILE_WITH_GUI_