nlist: make selected list accessible globally
[waspsaliva.git] / src / irrlicht_changes / static_text.cpp
blobbf61cd64eb3e9fb5d25c983745aa95d0691dad25
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_
10 #include <IGUIFont.h>
11 #include <IVideoDriver.h>
12 #include <rect.h>
13 #include <SColor.h>
15 #if USE_FREETYPE
16 #include "CGUITTFont.h"
17 #endif
19 #include "util/string.h"
21 namespace irr
24 #if USE_FREETYPE
26 namespace gui
28 //! constructor
29 StaticText::StaticText(const EnrichedString &text, bool border,
30 IGUIEnvironment* environment, IGUIElement* parent,
31 s32 id, const core::rect<s32>& rectangle,
32 bool background)
33 : IGUIStaticText(environment, parent, id, rectangle),
34 HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT),
35 Border(border), WordWrap(false), Background(background),
36 RestrainTextInside(true), RightToLeft(false),
37 OverrideFont(0), LastBreakFont(0)
39 #ifdef _DEBUG
40 setDebugName("StaticText");
41 #endif
43 setText(text);
47 //! destructor
48 StaticText::~StaticText()
50 if (OverrideFont)
51 OverrideFont->drop();
54 //! draws the element and its children
55 void StaticText::draw()
57 if (!IsVisible)
58 return;
60 IGUISkin* skin = Environment->getSkin();
61 if (!skin)
62 return;
63 video::IVideoDriver* driver = Environment->getVideoDriver();
65 core::rect<s32> frameRect(AbsoluteRect);
67 // draw background
69 if (Background)
70 driver->draw2DRectangle(getBackgroundColor(), frameRect, &AbsoluteClippingRect);
72 // draw the border
74 if (Border)
76 skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect);
77 frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
80 // draw the text
81 IGUIFont *font = getActiveFont();
82 if (font && BrokenText.size()) {
83 if (font != LastBreakFont)
84 updateText();
86 core::rect<s32> r = frameRect;
87 s32 height_line = font->getDimension(L"A").Height + font->getKerningHeight();
88 s32 height_total = height_line * BrokenText.size();
89 if (VAlign == EGUIA_CENTER && WordWrap)
91 r.UpperLeftCorner.Y = r.getCenter().Y - (height_total / 2);
93 else if (VAlign == EGUIA_LOWERRIGHT)
95 r.UpperLeftCorner.Y = r.LowerRightCorner.Y - height_total;
97 if (HAlign == EGUIA_LOWERRIGHT)
99 r.UpperLeftCorner.X = r.LowerRightCorner.X -
100 getTextWidth();
103 irr::video::SColor previous_color(255, 255, 255, 255);
104 for (const EnrichedString &str : BrokenText) {
105 if (HAlign == EGUIA_LOWERRIGHT)
107 r.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
108 font->getDimension(str.c_str()).Width;
111 //str = colorizeText(BrokenText[i].c_str(), colors, previous_color);
112 //if (!colors.empty())
113 // previous_color = colors[colors.size() - 1];
115 #if USE_FREETYPE
116 if (font->getType() == irr::gui::EGFT_CUSTOM) {
117 irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
118 tmp->draw(str,
119 r, previous_color, // FIXME
120 HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER,
121 (RestrainTextInside ? &AbsoluteClippingRect : NULL));
122 } else
123 #endif
125 // Draw non-colored text
126 font->draw(str.c_str(),
127 r, str.getDefaultColor(), // TODO: Implement colorization
128 HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER,
129 (RestrainTextInside ? &AbsoluteClippingRect : NULL));
133 r.LowerRightCorner.Y += height_line;
134 r.UpperLeftCorner.Y += height_line;
138 IGUIElement::draw();
142 //! Sets another skin independent font.
143 void StaticText::setOverrideFont(IGUIFont* font)
145 if (OverrideFont == font)
146 return;
148 if (OverrideFont)
149 OverrideFont->drop();
151 OverrideFont = font;
153 if (OverrideFont)
154 OverrideFont->grab();
156 updateText();
159 //! Gets the override font (if any)
160 IGUIFont * StaticText::getOverrideFont() const
162 return OverrideFont;
165 //! Get the font which is used right now for drawing
166 IGUIFont* StaticText::getActiveFont() const
168 if ( OverrideFont )
169 return OverrideFont;
170 IGUISkin* skin = Environment->getSkin();
171 if (skin)
172 return skin->getFont();
173 return 0;
176 //! Sets another color for the text.
177 void StaticText::setOverrideColor(video::SColor color)
179 ColoredText.setDefaultColor(color);
180 updateText();
184 //! Sets another color for the text.
185 void StaticText::setBackgroundColor(video::SColor color)
187 ColoredText.setBackground(color);
188 Background = true;
192 //! Sets whether to draw the background
193 void StaticText::setDrawBackground(bool draw)
195 Background = draw;
199 //! Gets the background color
200 video::SColor StaticText::getBackgroundColor() const
202 IGUISkin *skin = Environment->getSkin();
204 return (ColoredText.hasBackground() || !skin) ?
205 ColoredText.getBackground() : skin->getColor(gui::EGDC_3D_FACE);
209 //! Checks if background drawing is enabled
210 bool StaticText::isDrawBackgroundEnabled() const
212 return Background;
216 //! Sets whether to draw the border
217 void StaticText::setDrawBorder(bool draw)
219 Border = draw;
223 //! Checks if border drawing is enabled
224 bool StaticText::isDrawBorderEnabled() const
226 return Border;
230 void StaticText::setTextRestrainedInside(bool restrainTextInside)
232 RestrainTextInside = restrainTextInside;
236 bool StaticText::isTextRestrainedInside() const
238 return RestrainTextInside;
242 void StaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
244 HAlign = horizontal;
245 VAlign = vertical;
249 #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7
250 const video::SColor& StaticText::getOverrideColor() const
251 #else
252 video::SColor StaticText::getOverrideColor() const
253 #endif
255 return ColoredText.getDefaultColor();
259 //! Sets if the static text should use the overide color or the
260 //! color in the gui skin.
261 void StaticText::enableOverrideColor(bool enable)
263 // TODO
267 bool StaticText::isOverrideColorEnabled() const
269 return true;
273 //! Enables or disables word wrap for using the static text as
274 //! multiline text control.
275 void StaticText::setWordWrap(bool enable)
277 WordWrap = enable;
278 updateText();
282 bool StaticText::isWordWrapEnabled() const
284 return WordWrap;
288 void StaticText::setRightToLeft(bool rtl)
290 if (RightToLeft != rtl)
292 RightToLeft = rtl;
293 updateText();
298 bool StaticText::isRightToLeft() const
300 return RightToLeft;
304 //! Breaks the single text line.
305 // Updates the font colors
306 void StaticText::updateText()
308 const EnrichedString &cText = ColoredText;
309 BrokenText.clear();
311 if (cText.hasBackground())
312 setBackgroundColor(cText.getBackground());
313 else
314 setDrawBackground(false);
316 if (!WordWrap) {
317 BrokenText.push_back(cText);
318 return;
321 // Update word wrap
323 IGUISkin* skin = Environment->getSkin();
324 IGUIFont* font = getActiveFont();
325 if (!font)
326 return;
328 LastBreakFont = font;
330 EnrichedString line;
331 EnrichedString word;
332 EnrichedString whitespace;
333 s32 size = cText.size();
334 s32 length = 0;
335 s32 elWidth = RelativeRect.getWidth();
336 if (Border)
337 elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
338 wchar_t c;
340 //std::vector<irr::video::SColor> colors;
342 // We have to deal with right-to-left and left-to-right differently
343 // However, most parts of the following code is the same, it's just
344 // some order and boundaries which change.
345 if (!RightToLeft)
347 // regular (left-to-right)
348 for (s32 i=0; i<size; ++i)
350 c = cText.getString()[i];
351 bool lineBreak = false;
353 if (c == L'\r') // Mac or Windows breaks
355 lineBreak = true;
356 //if (Text[i+1] == L'\n') // Windows breaks
358 // Text.erase(i+1);
359 // --size;
361 c = '\0';
363 else if (c == L'\n') // Unix breaks
365 lineBreak = true;
366 c = '\0';
369 bool isWhitespace = (c == L' ' || c == 0);
370 if ( !isWhitespace )
372 // part of a word
373 //word += c;
374 word.addChar(cText, i);
377 if ( isWhitespace || i == (size-1))
379 if (word.size())
381 // here comes the next whitespace, look if
382 // we must break the last word to the next line.
383 const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
384 //const std::wstring sanitized = removeEscapes(word.c_str());
385 const s32 wordlgth = font->getDimension(word.c_str()).Width;
387 if (wordlgth > elWidth)
389 // This word is too long to fit in the available space, look for
390 // the Unicode Soft HYphen (SHY / 00AD) character for a place to
391 // break the word at
392 int where = core::stringw(word.c_str()).findFirst( wchar_t(0x00AD) );
393 if (where != -1)
395 EnrichedString first = word.substr(0, where);
396 EnrichedString second = word.substr(where, word.size() - where);
397 first.addCharNoColor(L'-');
398 BrokenText.push_back(line + first);
399 const s32 secondLength = font->getDimension(second.c_str()).Width;
401 length = secondLength;
402 line = second;
404 else
406 // No soft hyphen found, so there's nothing more we can do
407 // break to next line
408 if (length)
409 BrokenText.push_back(line);
410 length = wordlgth;
411 line = word;
414 else if (length && (length + wordlgth + whitelgth > elWidth))
416 // break to next line
417 BrokenText.push_back(line);
418 length = wordlgth;
419 line = word;
421 else
423 // add word to line
424 line += whitespace;
425 line += word;
426 length += whitelgth + wordlgth;
429 word.clear();
430 whitespace.clear();
433 if ( isWhitespace && c != 0)
435 whitespace.addChar(cText, i);
438 // compute line break
439 if (lineBreak)
441 line += whitespace;
442 line += word;
443 BrokenText.push_back(line);
444 line.clear();
445 word.clear();
446 whitespace.clear();
447 length = 0;
452 line += whitespace;
453 line += word;
454 BrokenText.push_back(line);
456 else
458 // right-to-left
459 for (s32 i=size; i>=0; --i)
461 c = cText.getString()[i];
462 bool lineBreak = false;
464 if (c == L'\r') // Mac or Windows breaks
466 lineBreak = true;
467 //if ((i>0) && Text[i-1] == L'\n') // Windows breaks
469 // Text.erase(i-1);
470 // --size;
472 c = '\0';
474 else if (c == L'\n') // Unix breaks
476 lineBreak = true;
477 c = '\0';
480 if (c==L' ' || c==0 || i==0)
482 if (word.size())
484 // here comes the next whitespace, look if
485 // we must break the last word to the next line.
486 const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
487 const s32 wordlgth = font->getDimension(word.c_str()).Width;
489 if (length && (length + wordlgth + whitelgth > elWidth))
491 // break to next line
492 BrokenText.push_back(line);
493 length = wordlgth;
494 line = word;
496 else
498 // add word to line
499 line = whitespace + line;
500 line = word + line;
501 length += whitelgth + wordlgth;
504 word.clear();
505 whitespace.clear();
508 if (c != 0)
509 // whitespace = core::stringw(&c, 1) + whitespace;
510 whitespace = cText.substr(i, 1) + whitespace;
512 // compute line break
513 if (lineBreak)
515 line = whitespace + line;
516 line = word + line;
517 BrokenText.push_back(line);
518 line.clear();
519 word.clear();
520 whitespace.clear();
521 length = 0;
524 else
526 // yippee this is a word..
527 //word = core::stringw(&c, 1) + word;
528 word = cText.substr(i, 1) + word;
532 line = whitespace + line;
533 line = word + line;
534 BrokenText.push_back(line);
539 //! Sets the new caption of this element.
540 void StaticText::setText(const wchar_t* text)
542 setText(EnrichedString(text, getOverrideColor()));
545 void StaticText::setText(const EnrichedString &text)
547 ColoredText = text;
548 IGUIElement::setText(ColoredText.c_str());
549 updateText();
552 void StaticText::updateAbsolutePosition()
554 IGUIElement::updateAbsolutePosition();
555 updateText();
559 //! Returns the height of the text in pixels when it is drawn.
560 s32 StaticText::getTextHeight() const
562 IGUIFont* font = getActiveFont();
563 if (!font)
564 return 0;
566 if (WordWrap) {
567 s32 height = font->getDimension(L"A").Height + font->getKerningHeight();
568 return height * BrokenText.size();
570 // There may be intentional new lines without WordWrap
571 return font->getDimension(BrokenText[0].c_str()).Height;
575 s32 StaticText::getTextWidth() const
577 IGUIFont *font = getActiveFont();
578 if (!font)
579 return 0;
581 s32 widest = 0;
583 for (const EnrichedString &line : BrokenText) {
584 s32 width = font->getDimension(line.c_str()).Width;
586 if (width > widest)
587 widest = width;
590 return widest;
594 //! Writes attributes of the element.
595 //! Implement this to expose the attributes of your element for
596 //! scripting languages, editors, debuggers or xml serialization purposes.
597 void StaticText::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
599 IGUIStaticText::serializeAttributes(out,options);
601 out->addBool ("Border", Border);
602 out->addBool ("OverrideColorEnabled",true);
603 out->addBool ("OverrideBGColorEnabled",ColoredText.hasBackground());
604 out->addBool ("WordWrap", WordWrap);
605 out->addBool ("Background", Background);
606 out->addBool ("RightToLeft", RightToLeft);
607 out->addBool ("RestrainTextInside", RestrainTextInside);
608 out->addColor ("OverrideColor", ColoredText.getDefaultColor());
609 out->addColor ("BGColor", ColoredText.getBackground());
610 out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
611 out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
613 // out->addFont ("OverrideFont", OverrideFont);
617 //! Reads attributes of the element
618 void StaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
620 IGUIStaticText::deserializeAttributes(in,options);
622 Border = in->getAttributeAsBool("Border");
623 setWordWrap(in->getAttributeAsBool("WordWrap"));
624 Background = in->getAttributeAsBool("Background");
625 RightToLeft = in->getAttributeAsBool("RightToLeft");
626 RestrainTextInside = in->getAttributeAsBool("RestrainTextInside");
627 if (in->getAttributeAsBool("OverrideColorEnabled"))
628 ColoredText.setDefaultColor(in->getAttributeAsColor("OverrideColor"));
629 if (in->getAttributeAsBool("OverrideBGColorEnabled"))
630 ColoredText.setBackground(in->getAttributeAsColor("BGColor"));
632 setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
633 (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
635 // OverrideFont = in->getAttributeAsFont("OverrideFont");
638 } // end namespace gui
640 #endif // USE_FREETYPE
642 } // end namespace irr
645 #endif // _IRR_COMPILE_WITH_GUI_