diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h new file mode 100644 index 000000000..5c22f7110 --- /dev/null +++ b/code/nel/include/nel/gui/view_text.h @@ -0,0 +1,413 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_VIEW_TEXT_H +#define NL_VIEW_TEXT_H + +#include "nel/gui/view_base.h" +#include "nel/gui/string_case.h" +#include "nel/3d/u_text_context.h" + +namespace NLGUI +{ + class CCtrlToolTip; + + /** + * class implementing a text view + * \author Matthieu 'TrapII' Besson + * \author Nicolas Vizerie + * \author Nevrax France + * \date 2002 + */ + class CViewText : public CViewBase + { + public: + enum TTextMode { ClipWord, DontClipWord, Justified }; + public: + + DECLARE_UI_CLASS(CViewText) + + + /// Constructor + CViewText (const TCtorParam ¶m); + + /// Constructor + CViewText (const std::string& id, const std::string Text="", sint FontSize=12, + NLMISC::CRGBA Color=NLMISC::CRGBA(255,255,255), bool Shadow=false); + + virtual ~CViewText(); + + CViewText &operator=(const CViewText &vt); + + void parseTextOptions (xmlNodePtr cur); + bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup); + virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } + + /// Updating + virtual void draw (); + void updateTextContext (); + virtual void checkCoords(); + virtual void updateCoords(); + virtual void onAddToGroup(); + + /// From CInterfaceElement + sint32 getMaxUsedW() const; + sint32 getMinUsedW() const; + + /// Accessors + + /// Set + + void setText (const ucstring &text); + void setFontSize (sint nFontSize); + void setColor (const NLMISC::CRGBA &color); + void setShadow (bool bShadow); + void setShadowColor (const NLMISC::CRGBA &color); + void setLineMaxW (sint nMaxW, bool invalidate=true); + void setMultiLine (bool bMultiLine); + void setMultiLineSpace (sint nMultiLineSpace); + void setMultiLineMaxWOnly (bool state); + void setMultiLineClipEndSpace (bool state); // use it for multiline edit box for instance + void setFirstLineX (uint firstLineX); + void setMultiMaxLine(uint l) { _MultiMaxLine = l; } + + // Force only a subset of letter to be displayed. Default is 0/0xFFFFFFFF + void enableStringSelection(uint start, uint end); + void disableStringSelection(); + + /// Get + + ucstring getText() const { return _Text; } + sint getFontSize() const; + NLMISC::CRGBA getColor() { return _Color; } + bool getShadow() { return _Shadow; } + NLMISC::CRGBA getShadowColor() { return _ShadowColor; } + sint getLineMaxW() const { return _LineMaxW; } + bool getMultiLine() const { return _MultiLine; } + sint getMultiLineSpace() const { return _MultiLineSpace; } + bool getMultiLineMaxWOnly() const { return _MultiLineMaxWOnly; } + uint32 getMultiMaxLine() const { return _MultiMaxLine; } + + // get current Hint font width, in pixels + uint getFontWidth() const; + // get current font height, in pixels + uint getFontHeight() const; + // get current font leg height, in pixels + uint getFontLegHeight() const; + // Set the display mode (supported with multiline only for now) + void setTextMode(TTextMode mode); + TTextMode getTextMode() const { return _TextMode; } + uint getNumLine() const; + uint getFirstLineX() const; + uint getLastLineW () const; + void setUnderlined (bool underlined) { _Underlined = underlined; } + bool getUnderlined () const { return _Underlined; } + // true if the viewText is a single line clamped. + bool isSingleLineTextClamped() const {return _SingleLineTextClamped;} + + // Character positions + + /** Get position of the ith character, position are relative to the BR corner of the text. + * \param lineEnd. When set to true, return the coordinate of the previous line if the index is at the start of a line. + * When looking at standard edit box, we see that if a line is split accross to line with no + * This also returns the height of the line + */ + void getCharacterPositionFromIndex(sint index, bool lineEnd, sint &x, sint &y, sint &height) const; + /** From a coordinate relative to the BR BR corner of the text, return the index of a character. + * If no character is found at the given position, the closest character is returned (first or last character, for the line or the whole text) + */ + void getCharacterIndexFromPosition(sint x, sint y, uint &index, bool &lineEnd) const; + /** From a character index, get the index of the line it belongs to, or -1 if the index is invalid + * \param cursorDisplayedAtEndOfPreviousLine true if the cursor is displayed at the end of the previous line that match its index + */ + sint getLineFromIndex(uint index, bool cursorDisplayedAtEndOfPreviousLine = true) const; + /// From a line number, get the character at which it starts, or -1 if invalid + sint getLineStartIndex(uint line) const; + /// From a line number, get the character at which it ends (not including any '\n' ), or -1 if invalid + void getLineEndIndex(uint line, sint &index, bool &endOfPreviousLine) const; + + std::string getHardText() const { std::string result; _Text.toString (result); return result; } + void setHardText (const std::string &ht); + + std::string getColorAsString() const; + void setColorAsString(const std::string &ht); + + NLMISC::CRGBA getColorRGBA() const; + void setColorRGBA(NLMISC::CRGBA col); + + virtual sint32 getAlpha() const { return _Color.A; } + virtual void setAlpha (sint32 a) { _ShadowColor.A = _Color.A = (uint8)a; } + + /** Setup a Text with Format Tags. Text is store without color/format tags, and special array is allocated for Format association + */ + void setTextFormatTaged(const ucstring &text); + + void setSingleLineTextFormatTaged(const ucstring &text); + + // Remove end space + void removeEndSpaces(); + + // Reset the text index because the text context has changed + void resetTextIndex(); + + // Case mode + void setCaseMode (TCaseMode caseMode); + TCaseMode getCaseMode () const; + + // OverExtendViewText + void setOverExtendViewText(bool state) {_OverExtendViewText= state;} + bool getOverExtendViewText() const {return _OverExtendViewText;} + + // OverExtendViewTextUseParentRect + void setOverExtendViewTextUseParentRect(bool state) {_OverExtendViewTextUseParentRect= state;} + bool getOverExtendViewTextUseParentRect() const {return _OverExtendViewTextUseParentRect;} + + // see if text ellipsis if done at right side of the text + bool isClampRight() const { return _ClampRight; } + + int luaSetLineMaxW(CLuaState &ls); + + REFLECT_EXPORT_START(CViewText, CViewBase) + REFLECT_STRING("hardtext", getHardText, setHardText); + REFLECT_UCSTRING("uc_hardtext", getText, setText); + REFLECT_UCSTRING("uc_hardtext_format", getText, setTextFormatTaged); + REFLECT_UCSTRING("uc_hardtext_single_line_format", getText, setSingleLineTextFormatTaged); + REFLECT_STRING ("color", getColorAsString, setColorAsString); + REFLECT_RGBA ("color_rgba", getColorRGBA, setColorRGBA); + REFLECT_SINT32 ("alpha", getAlpha, setAlpha); + REFLECT_BOOL ("overExtendViewText", getOverExtendViewText, setOverExtendViewText); + REFLECT_BOOL ("overExtendViewTextUseParentRect", getOverExtendViewTextUseParentRect, setOverExtendViewTextUseParentRect); + REFLECT_LUA_METHOD("setLineMaxW", luaSetLineMaxW); + REFLECT_EXPORT_END + + + virtual void serial(NLMISC::IStream &f); + + protected: + + /// Text to display. + ucstring _Text; + /// index of the computed String associated to this text control + uint _Index; + /// info on the computed String associated to this text control + NL3D::UTextContext::CStringInfo _Info; + /// the font size + sint _FontSize; + // width of the font in pixel. Just a Hint for tabing format (computed with '_') + uint _FontWidth; + // height of the font in pixel. + // use getFontHeight + uint _FontHeight; + uint _FontLegHeight; + float _SpaceWidth; + /// the text color + NLMISC::CRGBA _Color; + /// the shadow mode + bool _Shadow; + /// the case mode + TCaseMode _CaseMode; + /// the text shadow color + NLMISC::CRGBA _ShadowColor; + /// Is the line (under p loop) should be considered at bottom (if false bottom is under p leg) + /// maxw for the line/multiline + sint32 _LineMaxW; + /// For single line, true if the text is clamped (ie displayed with "...") + bool _SingleLineTextClamped; + + /// Multiple lines handling + bool _MultiLine; + bool _MultiLineMaxWOnly; + bool _MultiLineClipEndSpace; + uint8 _AutoClampOffset; + TTextMode _TextMode; + sint _MultiLineSpace; + sint _LastMultiLineMaxW; + uint32 _MultiMaxLine; + + + /// FormatTag handling + struct CFormatInfo + { + // The color to change + NLMISC::CRGBA Color; + // The Tabulation to apply, in number of "_" characters. + uint TabX; + // Index in vector + sint IndexTt; + + CFormatInfo() + { + Color= NLMISC::CRGBA::White; + TabX= 0; + IndexTt = -1; + } + + bool operator==(const CFormatInfo &o) const {return Color==o.Color && TabX==o.TabX && IndexTt==o.IndexTt;} + bool operator!=(const CFormatInfo &o) const {return !operator==(o);} + }; + struct CFormatTag : public CFormatInfo + { + uint Index; + + // compare 2 tags, not a tag and a CFormatInfo + bool sameTag(const CFormatTag &o) const + { + return CFormatInfo::operator==(o) && Index==o.Index; + } + }; + std::vector _FormatTags; + + /// Get the current maxW for multiline, accordgin to parent and _MultiLineOptionMaxW + sint getCurrentMultiLineMaxW() const; + + + + + NL3D::ULetterColors * _LetterColors; + + private: + // A word in a line + class CWord + { + public: + // default ctor + CWord(uint numSpaces = 0) : Index(0), NumSpaces(numSpaces) {} + ucstring Text; + uint Index; // index of the info for this word + NL3D::UTextContext::CStringInfo Info; + uint NumSpaces; // number of spaces before this word + // The specialized color/format of this word. White if none + CFormatInfo Format; + public: + // build from a string, using the current text context + void build(const ucstring &text, uint numSpaces= 0); + }; + typedef std::vector TWordVect; + + // A line of text (which is made of one word with space, or of several words with no spaces in them) + class CLine : public NLMISC::CRefCount + { + public: + // ctor + CLine(); + // Clear the line & remove text contexts + void clear(); + // Add a new word (and its context) in the line + a number of spaces to append at the end of the line + void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, uint fontWidth); + void addWord(const CWord &word, uint fontWidth); + uint getNumWords() const { return (uint)_Words.size(); } + CWord &getWord(uint index) { return _Words[index]; } + float getSpaceWidth() const { return _SpaceWidth; } + void setSpaceWidth(float width) { _SpaceWidth = width; } + // Get the number of chars in the line, not counting the end spaces, but couting the spaces in words + uint getNumChars() const { return _NumChars; } + // Get the total number of spaces between words (not including those in words, but there should not be if text is justified) + uint getNumSpaces() const { return _NumSpaces; } + float getStringLine() const { return _StringLine; } + float getWidthWithoutSpaces() const { return _WidthWithoutSpaces; } + // get total width including spaces, but not including end spaces + float getWidth() const { return _WidthWithoutSpaces + _SpaceWidth * _NumSpaces; } + // Get the number of spaces at the end of the line + void setEndSpaces(uint numSpaces) { _EndSpaces = numSpaces; } + // Set the number of spaces at the end of the line + uint getEndSpaces() const { return _EndSpaces; } + // Test if there's a line feed at the end of the line + bool getLF() const { return _HasLF; } + void setLF(bool lf) { _HasLF = lf; } + void resetTextIndex(); + private: + TWordVect _Words; + uint _NumChars; + uint _NumSpaces; + float _SpaceWidth; // width of a space, in pixels (used with multispace alignment) + float _StringLine; + float _WidthWithoutSpaces; // width without space (see the Field NumSpaces in the CWord class). + // NB : space inserted inside a word are counted, however! + uint _EndSpaces; // spaces at the end of the line + bool _HasLF; // a linefeed is at end of line (no breaking due to line full) + }; + /// NB : we keep pointers on lines (each line contains a vector, that we don't want to be copied, and this occurs as the vector of lines grows..) + + typedef NLMISC::CSmartPtr TLineSPtr; + typedef std::vector TLinePtVect; + private: + /** Data of the updated text for multiline. It is built from the _Text field in the updateTextContext member function, + * and is used to perform the draw + */ + TLinePtVect _Lines; + + /// if true, and if the view text is isSingleLineTextClamped(), then an over will be drawn, with the text + bool _OverExtendViewText : 1; + /// if true and _OverExtendViewText true too, use the parent rectangle to know if must display the over or not + bool _OverExtendViewTextUseParentRect : 1; + /// Letter selection handling + bool _AutoClamp : 1; + bool _ClampRight : 1; + bool _TextSelection : 1; + bool _InvalidTextContext : 1; + bool _Underlined : 1; + bool _ContinuousUpdate : 1; + bool _Setuped : 1; + + uint _TextSelectionStart; + uint _TextSelectionEnd; + + // First line X coordinate + uint _FirstLineX; + + /// Dynamic tooltips + std::vector _Tooltips; + + + private: + void setup (); + void setupDefault (); + + void setStringSelectionSkipingSpace(uint stringId, const ucstring &text, sint charStart, sint charEnd); + + // void pushString(const ucstring &str, bool deleteSpaceAtStart = false); + + /// \from CInterfaceElement + void onInvalidateContent(); + + // may append a new line, and append a word to the last line (no spaces) + void flushWordInLine(ucstring &ucCurrentWord, bool &linePushed, const CFormatInfo &wordFormat); + // Clear all the lines and free their datas + void clearLines(); + // Update in the case of a multiline text + void updateTextContextMultiLine(uint nMaxWidth); + // Update in the case of a multiline text with justification + void updateTextContextMultiLineJustified(uint nMaxWidth, bool expandSpaces); + // Recompute font size info + void computeFontSize (); + + // used for "donctClipWord" case in updateTextContextMultiLineJustified(). currLine is reseted + void addDontClipWordLine(std::vector &currLine); + + // FormatTag build. + static void buildFormatTagText(const ucstring &text, ucstring &textBuild, std::vector &formatTags, std::vector &tooltips); + // FormatTag parsing. + bool isFormatTagChange(uint textIndex, uint ctIndex) const; + void getFormatTagChange(uint textIndex, uint &ctIndex, CFormatInfo &wordFormat) const; + }; + +} + +#endif // NL_VIEW_TEXT_H + +/* End of view_text.h */ diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp new file mode 100644 index 000000000..4c29b5146 --- /dev/null +++ b/code/nel/src/gui/view_text.cpp @@ -0,0 +1,2603 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/bit_mem_stream.h" +#include "nel/misc/i18n.h" + +#include "nel/gui/view_text.h" +#include "nel/gui/view_renderer.h" +#include "nel/gui/widget_manager.h" +#include "nel/gui/group_container_base.h" +#include "nel/gui/ctrl_tooltip.h" +#include "nel/misc/xml_auto_ptr.h" +#include "nel/gui/lua_ihm.h" +#include "nel/gui/view_pointer_base.h" + +using namespace std; +using namespace NLMISC; +using namespace NL3D; + +typedef std::string::size_type TCharPos; // index of a chracter in a string + +REGISTER_UI_CLASS(CViewText) + +namespace NLGUI +{ + + // *************************************************************************** + void CViewText::setupDefault () + { + _CaseMode = CaseNormal; + _Underlined = false; + _ContinuousUpdate = false; + _Active = true; + _X = 0; + _Y = 0; + _W = 0;; + _H = 0; + _SizeRef = 0; + _SizeDivW = 10; + _SizeDivH = 10; + _ParentPosRef = Hotspot_BL; + _PosRef = Hotspot_BL; + + _FontSize = 12 + + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont ).getValSInt32(); + _Color = CRGBA(255,255,255,255); + _Shadow = false; + _ShadowColor = CRGBA(0,0,0,255); + + _MultiLine = false; + _TextMode = DontClipWord; + _MultiLineSpace = 8; + _LineMaxW = 16384; + _MultiLineMaxWOnly = false; + _MultiLineClipEndSpace = false; + _LastMultiLineMaxW = 0; + _MultiMaxLine = 0; + _Index = 0xFFFFFFFF; + + _FontWidth= 0; + _FontHeight = 0; + _FontLegHeight = 0; + + _TextSelection= false; + _TextSelectionStart= 0; + _TextSelectionEnd= std::numeric_limits::max(); + + _InvalidTextContext= true; + _FirstLineX = 0; + computeFontSize (); + + _SingleLineTextClamped= false; + _OverExtendViewText= false; + _OverExtendViewTextUseParentRect= false; + + _AutoClamp = false; + _ClampRight = true; // clamp on the right of the text + + _LetterColors = NULL; + _Setuped= false; + _AutoClampOffset = 0; + } + + // *************************************************************************** + + NLMISC_REGISTER_OBJECT(CViewBase, CViewText, std::string, "text"); + + CViewText::CViewText(const TCtorParam ¶m) + :CViewBase(param) + { + setupDefault (); + } + + ///constructor + // *************************************************************************** + CViewText:: CViewText (const std::string& id, const std::string Text, sint FontSize, + NLMISC::CRGBA Color, bool Shadow) + :CViewBase(TCtorParam()) + { + _Id = id; + setupDefault (); + + _FontSize = FontSize + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + _Color = Color; + _Shadow = Shadow; + setText(Text); + computeFontSize (); + } + + // *************************************************************************** + CViewText::~CViewText() + { + if (_Index != 0xFFFFFFFF) + CViewRenderer::getTextContext()->erase (_Index); + clearLines(); + + if (!_Setuped) + for (uint i=0 ; i<_Tooltips.size() ; ++i) + delete _Tooltips[i]; + + _Tooltips.clear(); + } + + // *************************************************************************** + CViewText &CViewText::operator=(const CViewText &vt) + { + if (_Index != 0xFFFFFFFF) + CViewRenderer::getTextContext()->erase (_Index); + + // Create database entries + _Active = vt._Active; + _X = vt._X; + _Y = vt._Y; + _W = vt._W; + _H = vt._H; + _SizeRef = vt._SizeRef; + _SizeDivW = vt._SizeDivW; + _SizeDivH = vt._SizeDivH; + _ParentPosRef = vt._ParentPosRef; + _PosRef = vt._PosRef; + + _FontSize = vt._FontSize; + _Color = vt._Color; + _Shadow = vt._Shadow; + _ShadowColor = vt._ShadowColor; + + _MultiLine = false; + _MultiLineSpace = 8; + _LineMaxW= 16384; + _MultiLineMaxWOnly = false; + _MultiLineClipEndSpace = false; + _LastMultiLineMaxW = 0; + _Index = 0xFFFFFFFF; + + _ModulateGlobalColor= vt._ModulateGlobalColor; + + + // remove previous lines + clearLines(); + _InvalidTextContext = true; + computeFontSize (); + + return *this; + } + + // *************************************************************************** + void CViewText::parseTextOptions (xmlNodePtr cur) + { + CXMLAutoPtr prop; + + prop= (char*) xmlGetProp( cur, (xmlChar*)"color" ); + _Color = CRGBA(255,255,255,255); + if (prop) + _Color = convertColor(prop); + + prop= (char*) xmlGetProp (cur, (xmlChar*)"global_color"); + if(prop) + _ModulateGlobalColor= convertBool(prop); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"fontsize" ); + _FontSize = 12 + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + if (prop) + { + fromString((const char*)prop, _FontSize); + _FontSize += CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + } + + prop = (char*) xmlGetProp( cur, (xmlChar*)"shadow" ); + _Shadow = false; + if (prop) + _Shadow = convertBool(prop); + + prop= (char*) xmlGetProp( cur, (xmlChar*)"shadow_color" ); + _ShadowColor = CRGBA(0,0,0,255); + if (prop) + _ShadowColor = convertColor(prop); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"multi_line" ); + _MultiLine = false; + if (prop) + _MultiLine = convertBool(prop); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"justification" ); + if (prop) + { + if (nlstricmp("clip_word", (const char *) prop) == 0) _TextMode = ClipWord; + else if (nlstricmp("dont_clip_word", (const char *) prop) == 0) _TextMode = DontClipWord; + else if (nlstricmp("justified", (const char *) prop) == 0) _TextMode = Justified; + else nlwarning(" bad text mode"); + } + + prop = (char*) xmlGetProp( cur, (xmlChar*)"line_maxw" ); + _LineMaxW = 16384; + if (prop) + fromString((const char*)prop, _LineMaxW); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"multi_line_space" ); + _MultiLineSpace = 8; + if (prop) + fromString((const char*)prop, _MultiLineSpace); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"multi_line_maxw_only" ); + _MultiLineMaxWOnly = false; + if (prop) + _MultiLineMaxWOnly = convertBool(prop); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"multi_max_line" ); + _MultiMaxLine = 0; + if (prop) + fromString((const char*)prop, _MultiMaxLine); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"underlined" ); + _Underlined = false; + if (prop) + _Underlined = convertBool(prop); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"case_mode" ); + _CaseMode = CaseNormal; + if (prop) + { + sint32 caseMode; + fromString((const char*)prop, caseMode); + _CaseMode = (TCaseMode)caseMode; + } + + prop = (char*) xmlGetProp( cur, (xmlChar*)"over_extend_view_text" ); + _OverExtendViewText= false; + if(prop) + _OverExtendViewText= convertBool(prop); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"over_extend_parent_rect" ); + _OverExtendViewTextUseParentRect= false; + if(prop) + _OverExtendViewTextUseParentRect= convertBool(prop); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"auto_clamp" ); + _AutoClamp = false; + if (prop) + _AutoClamp = convertBool(prop); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"clamp_right" ); + _ClampRight = true; + if (prop) + _ClampRight = convertBool(prop); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"auto_clamp_offset" ); + _AutoClampOffset = 0; + if (prop) + fromString((const char*)prop, _AutoClampOffset); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"continuous_update" ); + if (prop) + { + _ContinuousUpdate = convertBool(prop); + } + + + computeFontSize (); + } + + /* + * parse an xml node and initialize the base view mambers. Must call CViewBase::parse + * \param cur : pointer to the xml node to be parsed + * \param parentGroup : the parent group of the view + * \partam id : a refence to the string that will receive the view ID + * \return true if success + */ + // *************************************************************************** + bool CViewText::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup) + { + + // const ucstring* tmp; + CXMLAutoPtr prop; + //try to get props that can be inherited from groups + //if a property is not defined, try to find it in the parent group. + //if it is undefined, set it to zero + + if (! CViewBase::parse(cur,parentGroup) ) + return false; + + //set w and h to 0 : they depend on the string contained + _W = 0; + _H = 0; + + //try to get the NEEDED specific props + parseTextOptions(cur); + + prop = (char*) xmlGetProp( cur, (xmlChar*)"hardtext" ); + if (prop) + { + const char *propPtr = prop; + _Text = ucstring(propPtr); + + if ((strlen(propPtr)>2) && (propPtr[0] == 'u') && (propPtr[1] == 'i')) + _Text = CI18N::get (propPtr); + setCase (_Text, _CaseMode); + } + + prop = (char*) xmlGetProp( cur, (xmlChar*)"hardtext_format" ); + if (prop) + { + const char *propPtr = prop; + if (_MultiLine) + { + setTextFormatTaged(CI18N::get(propPtr)); + } + else + { + setSingleLineTextFormatTaged(CI18N::get(propPtr)); + } + } + + invalidateContent (); + + return true; + } + + // *************************************************************************** + sint CViewText::getCurrentMultiLineMaxW() const + { + if(_MultiLineMaxWOnly) + return _LineMaxW; + else + { + sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); + return std::min(parentWidth-(sint)(_XReal-_Parent->getXReal()), (sint)_LineMaxW); + } + } + + + // *************************************************************************** + void CViewText::checkCoords () + { + if ((_MultiLine)&&(_Parent != NULL)) + { + // If never setuped, and if text is not empty + if (_Lines.size() == 0 && !_Text.empty()) + invalidateContent (); + + sint currentMaxW= getCurrentMultiLineMaxW(); + if ( _LastMultiLineMaxW != currentMaxW ) + { + if (_ContinuousUpdate) + { + _LastMultiLineMaxW = currentMaxW; + invalidateContent(); + } + else + { + CCtrlBase *pCB = CWidgetManager::getInstance()->getCapturePointerLeft(); + if (pCB != NULL) + { + if( pCB->isResizer() ) + { + // We are resizing !!!! + } + else + { + _LastMultiLineMaxW = currentMaxW; + invalidateContent(); + } + } + else + { + _LastMultiLineMaxW = currentMaxW; + invalidateContent(); + } + } + } + } + else + { + if (_Index == 0xFFFFFFFF) + invalidateContent (); + } + } + /* + * draw the view + */ + // *************************************************************************** + void CViewText::draw () + { + H_AUTO( RZ_Interface_CViewText_draw ) + + CViewRenderer &rVR = *CViewRenderer::getInstance(); + + // *** Out Of Clip? + sint32 ClipX, ClipY, ClipW, ClipH; + rVR.getClipWindow (ClipX, ClipY, ClipW, ClipH); + if (((_XReal) > (ClipX+ClipW)) || ((_XReal+_WReal) < ClipX) || + ((_YReal) > (ClipY+ClipH)) || ((_YReal+_HReal) < ClipY)) + return; + + // *** Screen Minimized? + uint32 w, h; + float oow, ooh; + rVR.getScreenSize (w, h); + if (rVR.isMinimized()) + return; + rVR.getScreenOOSize (oow, ooh); + + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + + + // *** get current color + CRGBA col, shcol; + if(getModulateGlobalColor()) + { + CRGBA gcfc = CWidgetManager::getInstance()->getGlobalColorForContent(); + col.modulateFromColor (_Color, gcfc); + shcol.modulateFromColor (_ShadowColor, gcfc); + } + else + { + col = _Color; + shcol = _ShadowColor; + col.A = (uint8)(((sint)col.A*((sint)CWidgetManager::getInstance()->getGlobalColorForContent().A+1))>>8); + shcol.A = (uint8)(((sint)shcol.A*((sint)CWidgetManager::getInstance()->getGlobalColorForContent().A+1))>>8); + } + + + // *** Draw multiline + if ((_MultiLine)&&(_Parent != NULL)) + { + if (_Lines.size() == 0) return; + + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + + TextContext->setHotSpot (UTextContext::BottomLeft); + TextContext->setShaded (_Shadow); + TextContext->setShadeColor (shcol); + TextContext->setFontSize (_FontSize); + + float y = (float)(_YReal) * ooh; // y is expressed in scree, coordinates [0..1] + //y += _LinesInfos[_LinesInfos.size()-1].StringLine / h; + + // Y is the base line of the string, so it must be grown up. + y += (float)_FontLegHeight * ooh; + + sint y_line = _YReal+_FontLegHeight-2; + + // special selection code + if(_TextSelection) + { + sint charIndex = 0; + for (sint i = 0; i<(sint)_Lines.size(); i++) + { + CLine &currLine = *_Lines[i]; + for(uint k = 0; k < currLine.getNumWords(); ++k) + { + CWord &currWord = currLine.getWord(k); + charIndex += currWord.NumSpaces; + sint cStart= max(charIndex, (sint)_TextSelectionStart); + sint cEnd= min(charIndex+(sint)currWord.Text.length(), (sint)_TextSelectionEnd); + + // range must be valid + if(cStartsetStringSelection(currWord.Index, 0, 0); + } + + // next word + charIndex+= (sint)currWord.Text.length(); + } + charIndex += currLine.getEndSpaces() + (currLine.getLF() ? 1 : 0); + } + } + + // draw + for (sint i = (sint)_Lines.size()-1; i >= 0; --i) + { + CLine &currLine = *_Lines[i]; + // current x position + float px = (float) (_XReal + ((i==0) ? (sint)_FirstLineX : 0)); + // draw each words of the line + for(uint k = 0; k < currLine.getNumWords(); ++k) + { + CWord &currWord = currLine.getWord(k); + + // Change the current color + if(currWord.Format.Color==CRGBA::White) + TextContext->setStringColor(currWord.Index, col); + else + { + CRGBA mCol; + mCol.modulateFromColor(col, currWord.Format.Color); + TextContext->setStringColor(currWord.Index, mCol); + } + + // skip spaces before current word + float firstSpace = currWord.NumSpaces * currLine.getSpaceWidth(); + sint line_width = 0; + if (_Underlined) + { + line_width = (sint)floorf(currLine.getWidthWithoutSpaces() + currLine.getSpaceWidth()); + line_width -= (sint)floorf(firstSpace); + } + px += firstSpace; + // skip tabulation before current word + if(currWord.Format.TabX) + px= max(px, (float)(_XReal + currWord.Format.TabX*_FontWidth)); + + // draw. We take floorf px to avoid filtering of letters that are not located on a pixel boundary + rVR.drawText (_RenderLayer, floorf(px) * oow, y, currWord.Index, (float)ClipX * oow, (float)ClipY * ooh, + (float)(ClipX+ClipW) * oow, (float)(ClipY+ClipH) * ooh, *TextContext); + + // Draw a line + if (_Underlined) + rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line, line_width, 1, 0, false, rVR.getBlankTextureId(), col); + + // skip word + px += currWord.Info.StringWidth; + } + // go one line up + y += (_FontHeight + _MultiLineSpace) * ooh; + y_line += _FontHeight+_MultiLineSpace; + } + + // reset selection + if(_TextSelection) + { + for (sint i = 0; i<(sint)_Lines.size(); i++) + { + CLine &currLine = *_Lines[i]; + for(uint k = 0; k < currLine.getNumWords(); ++k) + { + TextContext->resetStringSelection(currLine.getWord(k).Index); + } + } + } + } + // *** Single Line Version (currently no support for text justification) + else + { + nlassert(_Index != 0xFFFFFFFF); + + TextContext->setHotSpot (UTextContext::BottomLeft); + TextContext->setShaded (_Shadow); + TextContext->setShadeColor (shcol); + TextContext->setFontSize (_FontSize); + + + if(_LetterColors!=NULL && !TextContext->isSameLetterColors(_LetterColors, _Index)) + { + TextContext->setLetterColors(_LetterColors, _Index); + } + + + float x = (float)(_XReal) * oow; + float y = (float)(_YReal) * ooh; + + // Y is the base line of the string, so it must be grown up. + y += (float)_FontLegHeight * ooh; + + // special selection code + if(_TextSelection) + // select subset. Arg, must skip spaces because not inserted in VertexBuffer. + setStringSelectionSkipingSpace(_Index, _Text, _TextSelectionStart, _TextSelectionEnd); + + // Change the current color + TextContext->setStringColor(_Index, col); + + // draw + rVR.drawText (_RenderLayer, x, y, _Index, (float)ClipX * oow, (float)ClipY * ooh, + (float)(ClipX+ClipW) * oow, (float)(ClipY+ClipH) * ooh, *TextContext); + + // Draw a line + if (_Underlined) + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_FontLegHeight-2, _WReal, 1, 0, false, rVR.getBlankTextureId(), col); + + // reset selection + if(_TextSelection) + TextContext->resetStringSelection(_Index); + + // if single line clamped, may allow to draw an over + if(isSingleLineTextClamped() && _OverExtendViewText && CWidgetManager::getInstance()->getPointer()) + { + // but must check first if mouse is over + sint32 x = CWidgetManager::getInstance()->getPointer()->getX(); + sint32 y = CWidgetManager::getInstance()->getPointer()->getY(); + bool mouseIn; + // use parent clip or self clip? + if(_OverExtendViewTextUseParentRect) + mouseIn= _Parent && _Parent->isIn(x,y); + else + mouseIn= isIn(x,y); + // if the mouse cursor is in the clip area + if(mouseIn) + { + // check the window under the mouse is the root window + CInterfaceGroup *pIG = CWidgetManager::getInstance()->getWindowUnder(x,y); + CInterfaceElement *pParent = this; + bool bFound = false; + while (pParent != NULL) + { + if (pParent == pIG) + { + bFound = true; + break; + } + pParent = pParent->getParent(); + } + + // ok => let this view text be the extend over one + if(bFound) + { + // last check: the window must not be currently moved + CGroupContainerBase *gc= dynamic_cast(pIG); + if(!gc || !gc->isMoving()) + { + CRGBA col= CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionViewTextOverBackColor).getValColor(); + CWidgetManager::getInstance()->setOverExtendViewText(this, col); + } + } + } + } + } + + } + + // *************************************************************************** + void CViewText::onAddToGroup() + { + // Add tooltips if not done + if(!_Setuped) + setup(); + } + + // *************************************************************************** + void CViewText::setTextMode(TTextMode mode) + { + if (mode != _TextMode) + { + _TextMode = mode; + invalidateContent (); + } + } + + // *************************************************************************** + void CViewText::setText(const ucstring & text) + { + // common case: no special format, no case mode => easy cache test + if (_FormatTags.empty() && _CaseMode==CaseNormal) + { + if (text != _Text) + { + _Text = text; + // no need to call "setCase (_Text, _CaseMode);" since CaseNormal: + invalidateContent (); + } + } + else + { + // if the view text had some format before, no choice, must recompute all + if(!_FormatTags.empty()) + { + _Text = text; + setCase (_Text, _CaseMode); + invalidateContent (); + } + // else test if after the case change the cache succeed + else + { + // compute the temp cased text + ucstring tempText= text; + setCase(tempText, _CaseMode); + if(tempText!=_Text) + { + _Text = tempText; + invalidateContent (); + } + } + } + + // clear format tags if any + _FormatTags.clear(); + } + + // *************************************************************************** + void CViewText::setFontSize (sint nFontSize) + { + _FontSize = nFontSize + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + computeFontSize (); + invalidateContent(); + } + + // *************************************************************************** + sint CViewText::getFontSize() const + { + return _FontSize - CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); + } + + // *************************************************************************** + void CViewText::setColor(const NLMISC::CRGBA & color) + { + _Color = color; + } + + // *************************************************************************** + void CViewText::setShadow (bool bShadow) + { + _Shadow = bShadow; + computeFontSize (); + invalidateContent(); + } + + // *************************************************************************** + void CViewText::setShadowColor(const NLMISC::CRGBA & color) + { + _ShadowColor = color; + } + + // *************************************************************************** + void CViewText::setLineMaxW (sint nMaxW, bool invalidate) + { + if(_LineMaxW!=nMaxW) + { + _LineMaxW = nMaxW; + if (invalidate) + invalidateContent(); + } + } + + // *************************************************************************** + int CViewText::luaSetLineMaxW(CLuaState &ls) + { + CLuaIHM::checkArgCount(ls, "setLineMaxW", 1); + sint32 value; + if(CLuaIHM::popSINT32(ls, value)) + { + setLineMaxW(value); + } + return 0; + } + + // *************************************************************************** + void CViewText::setMultiLine (bool bMultiLine) + { + _MultiLine = bMultiLine; + invalidateContent(); + } + + // *************************************************************************** + void CViewText::setMultiLineSpace (sint nMultiLineSpace) + { + _MultiLineSpace = nMultiLineSpace; + invalidateContent(); + } + + // *************************************************************************** + void CViewText::setMultiLineMaxWOnly (bool state) + { + _MultiLineMaxWOnly = state; + invalidateContent(); + } + + // *************************************************************************** + void CViewText::setMultiLineClipEndSpace (bool state) + { + _MultiLineClipEndSpace= state; + invalidateContent(); + } + + // *************************************************************************** + uint CViewText::getFontWidth() const + { + return _FontWidth; + } + + // *************************************************************************** + uint CViewText::getFontHeight() const + { + return _FontHeight; + } + + // *************************************************************************** + uint CViewText::getFontLegHeight() const + { + return _FontLegHeight; + } + + // *************************************************************************** + void CViewText::flushWordInLine(ucstring &ucCurrentWord, bool &linePushed, const CFormatInfo &wordFormat) + { + // create a new line? + if(!linePushed) + { + _Lines.push_back(TLineSPtr(new CLine)); + linePushed= true; + } + // Append to the last line + _Lines.back()->addWord(ucCurrentWord, 0, wordFormat, _FontWidth); + // reset the word + ucCurrentWord = ucstring(""); + } + + + // *************************************************************************** + void CViewText::updateTextContextMultiLine(uint nMaxWidth) + { + ucchar ucLetter; + UTextContext::CStringInfo si; + uint i; + // word state + ucstring ucCurrentWord; + CFormatInfo wordFormat; + // line state + float rWidthCurrentLine = 0, rWidthLetter; + bool linePushed= false; + // for all the text + uint textSize= (uint)_Text.size(); + uint formatTagIndex= 0; + for (i = 0; i < textSize; ++i) + { + if(isFormatTagChange(i, formatTagIndex)) + { + // If the word was not empty before this color tag + if(!ucCurrentWord.empty()) + flushWordInLine(ucCurrentWord, linePushed, wordFormat); + + // get new color and skip ctIndex. + getFormatTagChange(i, formatTagIndex, wordFormat); + + // Ensure the line witdh count the tab + rWidthCurrentLine= max(rWidthCurrentLine, (float)wordFormat.TabX*_FontWidth); + } + + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + + // Parse the letter + { + ucLetter = _Text[i]; + if (ucLetter == ucchar('\n')) + { + flushWordInLine(ucCurrentWord, linePushed, wordFormat); + // reset line state + linePushed= false; + rWidthCurrentLine = 0; + } + else + { + ucstring ucStrLetter; + ucStrLetter= ucLetter; + si = TextContext->getStringInfo (ucStrLetter); + rWidthLetter = (si.StringWidth); + if ((rWidthCurrentLine + rWidthLetter) > nMaxWidth) + { + flushWordInLine(ucCurrentWord, linePushed, wordFormat); + + // reset line state, and begin with the cut letter + linePushed= false; + rWidthCurrentLine = rWidthLetter; + ucCurrentWord = ucLetter; + } + else + { + // Grow the current word + ucCurrentWord += ucLetter; + rWidthCurrentLine += rWidthLetter; + } + } + } + } + if (ucCurrentWord.length()) + { + flushWordInLine(ucCurrentWord, linePushed, wordFormat); + } + } + + + // *************************************************************************** + void CViewText::addDontClipWordLine(std::vector &currLine) + { + // create a new line + _Lines.push_back(TLineSPtr(new CLine)); + + // Fill it with words. if all words of same color, create only one CWord + if (!currLine.empty()) + { + CFormatInfo lineWordFormat= currLine[0].Format; + ucstring lineWord; + for(uint i=0;iaddWord(lineWord, 0, lineWordFormat, _FontWidth); + // get new lineWordFormat + lineWordFormat= currLine[i].Format; + // and clear + lineWord.clear(); + } + + // Append the word with space to the lineWord. + ucstring blank; + blank.resize(currLine[i].NumSpaces, (ucchar) ' '); + lineWord += blank; + lineWord += currLine[i].Text; + } + + if(!lineWord.empty()) + _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth); + + // clear + currLine.clear(); + } + } + + // *************************************************************************** + void CViewText::updateTextContextMultiLineJustified(uint nMaxWidth, bool expandSpaces) + { + UTextContext::CStringInfo si; + // + TCharPos currPos = 0; + // + static const ucstring spaceStr(" "); + // precLineWidth valid only id precedent line is part of same paragraph. + float precLineWidth= 0; + float lineWidth = (float)_FirstLineX; // width of the current line + uint numWordsInLine = 0; // number of words in the current line + bool isParagraphStart = true; // A paragraph is a group of characters between 2 \n + bool lineFeed; + bool breakLine; + // + vector currLine; // if spaces are not expanded, all words of a line are inserted here (NB: index and stringInfo not filled) + ucstring wordValue; + CFormatInfo wordFormat; + uint formatTagIndex= 0; + // + while (currPos != _Text.length()) + { + TCharPos spaceEnd; + TCharPos wordEnd; + uint numSpaces; + float newLineWidth; + breakLine = false; + // + if (_Text[currPos] == (ucchar) '\n') + { + lineFeed = true; + } + else + { + lineFeed = false; + // Skip spaces and count them + spaceEnd = _Text.find_first_not_of(spaceStr, currPos); + if (spaceEnd == std::string::npos) + { + spaceEnd = _Text.length(); + } + numSpaces = (uint) (spaceEnd - currPos); + if (!isParagraphStart && numSpaces != 0 && numWordsInLine == 0) // Are these the first spaces of the line ? + { + if (!_Lines.empty()) + { + /* Yoyo: I changed this (added the "cut space"), because in editBox, it is so strange when + the word hit the end of line, and if you add spaces just after, nothing happens because + cursor pos is clamped at end of line. + */ + // Cannot put all of thoses spaces to the prec end of line? + if(_MultiLineClipEndSpace && precLineWidth + numSpaces * _SpaceWidth > nMaxWidth) + { + // put some of these spaces at the end of the previous line. + sint maxNumSpaces= (sint)floorf((nMaxWidth - precLineWidth) / _SpaceWidth); + _Lines.back()->setEndSpaces(maxNumSpaces); + // And start the new lines with the remaining spaces. + numSpaces-= maxNumSpaces; + currPos+= maxNumSpaces; + } + else + { + // ok, put all spaces to previous line + _Lines.back()->setEndSpaces(numSpaces); + currPos = spaceEnd; + numSpaces= 0; + } + if(currPos >=_Text.length()) + break; + } + } + + // Detect change of wordFormat at the begining of the word + if(isFormatTagChange((uint)spaceEnd, formatTagIndex)) + { + getFormatTagChange((uint)spaceEnd, formatTagIndex, wordFormat); + } + + // Get word until a space, a \n, or a FormatTagChange is encountered + uint i; + for(i= (uint)spaceEnd;i<(uint)_Text.length();i++) + { + ucchar c= _Text[i]; + if(c==' ' || c=='\n') + break; + // If change of color tag, stop the word, but don't take the new color now. + if(isFormatTagChange(i, formatTagIndex)) + break; + } + wordEnd = i; + + + // Get the word value. + wordValue = _Text.substr(spaceEnd, wordEnd - spaceEnd); + // compute width of word + si = CViewRenderer::getTextContext()->getStringInfo(wordValue); + + // compute size of spaces/Tab + word + newLineWidth = lineWidth + numSpaces * _SpaceWidth; + newLineWidth = max(newLineWidth, (float)wordFormat.TabX*_FontWidth); + newLineWidth+= si.StringWidth; + } + // + // Does the word go beyond the end of line ? + if (!lineFeed && newLineWidth > (float) nMaxWidth) + { + // Have we enough room for this word on a line ? + bool roomForThisWord = (numWordsInLine > 0) || ( (newLineWidth - lineWidth) < (float) nMaxWidth ); + + // not enough room for that word + // If it is the only word of the line, just split it + // Otherwise, scale the spaces between words so that the line as the maximum width + if (roomForThisWord) + { + if (expandSpaces) + { + nlassert(_Lines.size() > 0); + nlassert(_Lines.back()->getNumWords() > 0); + + // Yoyo: if the line has tab, then don't justify + if(wordFormat.TabX > 0) + _Lines.back()->setSpaceWidth(_SpaceWidth); + else + { + // Scale the width so that the line has the maximum width + float roomForSpaces = nMaxWidth - _Lines.back()->getWidthWithoutSpaces(); + uint startNumSpaces = _Lines.back()->getNumSpaces(); + if (startNumSpaces != 0) + { + _Lines.back()->setSpaceWidth(roomForSpaces / startNumSpaces); + } + else + { + _Lines.back()->setSpaceWidth(_SpaceWidth); + } + } + } + else + { + breakLine = true; + } + // we dont change the position in the input string so that the current will be processed on the next line + + } + else // it is the only word on the line.. + { + // .. so split it + // 1) Check if spaces go beyond the end of line + if (numSpaces * _SpaceWidth > nMaxWidth) + { + uint maxNumSpaces = std::max(1U, (uint) (nMaxWidth / _SpaceWidth)); + CWord spaceWord; // a word with only spaces in it + spaceWord.build (ucstring (""), maxNumSpaces); + spaceWord.Format= wordFormat; + _Lines.push_back(TLineSPtr(new CLine)); + _Lines.back()->addWord(spaceWord, _FontWidth); + if (expandSpaces) + { + _Lines.back()->setSpaceWidth(nMaxWidth / (float) maxNumSpaces); + } + else + { + _Lines.back()->setSpaceWidth(_SpaceWidth); + } + currPos = currPos + maxNumSpaces; + } + else + { + float px = numSpaces * _SpaceWidth; + uint currChar = 0; + ucstring oneChar(" "); + for(currChar = 0; currChar < wordValue.length(); ++currChar) + { + oneChar = wordValue[currChar]; + si = CViewRenderer::getTextContext()->getStringInfo(oneChar); + if ((uint) (px + si.StringWidth) > nMaxWidth) break; + px += si.StringWidth; + } + currChar = std::max((uint) 1, currChar); // must fit at least one character otherwise there's an infinite loop + wordValue = _Text.substr(spaceEnd, currChar); + CWord word; + word.build(wordValue, numSpaces); + word.Format= wordFormat; + _Lines.push_back(TLineSPtr(new CLine)); + float roomForSpaces = (float) nMaxWidth - word.Info.StringWidth; + if (expandSpaces && numSpaces != 0) + { + _Lines.back()->setSpaceWidth(roomForSpaces / (float) numSpaces); + } + else + { + _Lines.back()->setSpaceWidth(0); + } + _Lines.back()->addWord(word, _FontWidth); + currPos = currPos + numSpaces + currChar; + } + } + // reset line + numWordsInLine = 0; + precLineWidth= lineWidth; + lineWidth = 0; + isParagraphStart = false; + } + else if (!lineFeed) // the end of line hasn't been reached + { + if (expandSpaces) + { + // add in the current line (and create one if necessary) + if (numWordsInLine == 0) + { + _Lines.push_back(TLineSPtr(new CLine)); + _Lines.back()->setSpaceWidth(_SpaceWidth); + } + if (!wordValue.empty() || numSpaces != 0) + { + CWord word; + word.build(wordValue, numSpaces); + word.Format= wordFormat; + // update line width + _Lines.back()->addWord(word, _FontWidth); + ++numWordsInLine; + } + } + else + { + CWord word; + // Don't build here, this is used as temp data. + word.Text= wordValue; + word.NumSpaces= numSpaces; + word.Format= wordFormat; + // Append to the temp Data. + currLine.push_back(word); + + ++numWordsInLine; + } + lineWidth = newLineWidth; + currPos = wordEnd; + } + else + { + // '\n' was encountered + ++ currPos; + isParagraphStart = true; + } + if (lineFeed || breakLine) // '\n' was encoutered, or a linefeed has been asked + { + // !expandSpaces => insert minimum words according to word color. + if (!expandSpaces) + { + // Add the new line. + addDontClipWordLine(currLine); + // LineFeed? + if (lineFeed) + { + _Lines.back()->setLF(true); + } + } + // expandSpaces => just add a empty line. + else + { + if (numWordsInLine == 0) + { + // if nothing has been inserted in this line, create at least an empty line + _Lines.push_back(TLineSPtr(new CLine)); + } + if (lineFeed) + { + _Lines.back()->setLF(true); + } + } + lineWidth = 0.f; + numWordsInLine = 0; + } + } + + // if current line hasn't been pushed, add it + if (!expandSpaces && !currLine.empty()) + { + // Add new line + addDontClipWordLine(currLine); + } + + // if the text ends with \n, must insert the last line ourself + if (!_Text.empty() && _Text[_Text.length() - 1] == (ucchar) '\n') + { + _Lines.push_back(TLineSPtr(new CLine)); + } + } + + + // *************************************************************************** + void CViewText::updateTextContext () + { + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + + TextContext->setHotSpot (UTextContext::BottomLeft); + TextContext->setShaded (_Shadow); + TextContext->setFontSize (_FontSize); + + // default state + _SingleLineTextClamped= false; + + if ((_MultiLine)&&(_Parent != NULL)) + { + sint nMaxWidth = getCurrentMultiLineMaxW(); + _LastMultiLineMaxW = nMaxWidth; + clearLines(); + if (nMaxWidth <= 0) + { + // parent size may not be known yet + return; + } + switch(_TextMode) + { + case ClipWord: updateTextContextMultiLine(nMaxWidth); break; + case DontClipWord: updateTextContextMultiLineJustified(nMaxWidth, false); break; + case Justified: updateTextContextMultiLineJustified(nMaxWidth, true); break; + } + + // Special case for multiline limited in number of lines + if ((_Lines.size() > 0) && (_MultiMaxLine > 0) && (_Lines.size() > _MultiMaxLine)) + { + while (_Lines.size() > _MultiMaxLine) + { + _Lines.back()->clear(); + _Lines.pop_back(); + } + _Lines.pop_back(); + CViewText::CLine *endLine = new CViewText::CLine; + CViewText::CWord w; + w.build(string("...")); + endLine->addWord(w, _FontWidth); + _Lines.push_back(TLineSPtr(endLine)); + } + + // Calculate size + float rTotalW = 0; + for (uint i = 0; i < _Lines.size(); ++i) + { + rTotalW = std::max(_Lines[i]->getWidth() + ((i==0)?_FirstLineX:0), rTotalW); + } + _W = (sint)rTotalW; + _H = std::max(_FontHeight, uint(_FontHeight * _Lines.size() + std::max(0, sint(_Lines.size()) - 1) * _MultiLineSpace)); + + // Compute tooltips size + if (_Tooltips.size() > 0) + for (uint i=0 ; i<_Lines.size() ; ++i) + { + for (uint j=0 ; j<_Lines[i]->getNumWords() ; ++j) + { + CWord word = _Lines[i]->getWord(j); + // float w = _Lines[i]->getWidth(); + + if (word.Format.IndexTt != -1) + { + if (_Tooltips.size() > (uint)word.Format.IndexTt) + { + CCtrlToolTip *pTooltip = _Tooltips[word.Format.IndexTt]; + + sint y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - i - 1)); + + pTooltip->setX(0); + pTooltip->setY(y); + pTooltip->setW(getCurrentMultiLineMaxW()); + pTooltip->setH(_FontHeight); + } + } + } + } + } + else // Single line code + { + if (_Index != 0xFFFFFFFF) + TextContext->erase (_Index); + + // Common case: no W clamp + _Index = TextContext->textPush (_Text); + _Info = TextContext->getStringInfo (_Index); + _W = (sint)(_Info.StringWidth); + + // Rare case: clamp W => recompute slowly, cut letters + if(_W>_LineMaxW) + { + TextContext->erase (_Index); + + ucchar ucLetter; + UTextContext::CStringInfo si; + ucstring ucCurrentLine; + ucCurrentLine.reserve(_Text.size()); + // Append ... to the end of line + si = TextContext->getStringInfo (ucstring("...")); + float dotWidth= si.StringWidth; + float rWidthCurrentLine = 0, rWidthLetter; + // for all the text + if (_ClampRight) + { + for (uint i = 0; i < _Text.size(); ++i) + { + ucLetter= _Text[i]; + ucstring ucStrLetter; + ucStrLetter= ucLetter; + si = TextContext->getStringInfo (ucStrLetter); + rWidthLetter = (si.StringWidth); + if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW) + { + break; + } + else + { + // Grow the current line + ucCurrentLine += ucLetter; + rWidthCurrentLine += rWidthLetter; + } + } + + // Add the dots + ucCurrentLine+= "..."; + } + else + { + for (sint i = (sint)_Text.size() - 1; i >= 0; --i) + { + ucLetter= _Text[i]; + ucstring ucStrLetter; + ucStrLetter= ucLetter; + si = TextContext->getStringInfo (ucStrLetter); + rWidthLetter = (si.StringWidth); + if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW) + { + break; + } + else + { + // Grow the current line + ucCurrentLine = ucLetter + ucCurrentLine; + rWidthCurrentLine += rWidthLetter; + } + } + + // Add the dots + ucCurrentLine = "..." + ucCurrentLine; + } + + // And so setup this trunc text + _Index = TextContext->textPush (ucCurrentLine); + _Info = TextContext->getStringInfo (_Index); + _W = (sint)(_Info.StringWidth); + + _SingleLineTextClamped= true; + } + + // same height always + _H = _FontHeight; + } + + _InvalidTextContext= false; + } + + // *************************************************************************** + void CViewText::updateCoords() + { + if (_AutoClamp) + { + CViewBase::updateCoords (); + if (_Parent) + { + CInterfaceGroup *parent = _Parent; + // avoid resizing parents to compute the limiter + while (parent && (parent->getResizeFromChildW() || parent->isGroupList() )) + { + // NB nico : the dynamic_cast for CGroupList is bad!! + // can't avoid it for now, because, CGroupList implicitly does a "resize from child" in its update coords + // ... + parent = parent->getParent(); + } + if (parent) + { + if (_ClampRight) + { + sint32 parentRight = parent->getXReal() + parent->getWReal() - (sint32) _AutoClampOffset; + setLineMaxW(std::max((sint32) 0, parentRight - _XReal)); + } + else + { + sint32 parentLeft = parent->getXReal() + (sint32) _AutoClampOffset; + setLineMaxW(std::max((sint32) 0, _XReal + _WReal - parentLeft)); + } + } + } + } + + if(_InvalidTextContext) + updateTextContext(); + + CViewBase::updateCoords (); + } + + // *************************************************************************** + sint CViewText::getLineFromIndex(uint index, bool cursorDisplayedAtEndOfPreviousLine /* = true*/) const + { + if (index > _Text.length()) return -1; + if (_MultiLine) + { + uint charIndex = 0; + for(sint i = 0; i < (sint) _Lines.size(); ++i) + { + CLine &currLine = *_Lines[i]; + uint newCharIndex = charIndex + currLine.getNumChars() + currLine.getEndSpaces() + (currLine.getLF() ? 1 : 0); + if (newCharIndex > index) + { + if (i != 0 && cursorDisplayedAtEndOfPreviousLine && charIndex == index) + { + return i - 1; + } + else + { + return i; + } + } + charIndex = newCharIndex; + } + return (sint)_Lines.size() - 1; + } + else + { + return 0; + } + } + + // *************************************************************************** + sint CViewText::getLineStartIndex(uint line) const + { + uint charIndex = 0; + if (line >= _Lines.size()) return -1; + for(uint i = 0; i < line; ++i) + { + CLine &currLine = *_Lines[i]; + charIndex += currLine.getNumChars() + currLine.getEndSpaces() + (currLine.getLF() ? 1 : 0); + } + // skip all spaces at start of line (unless there are only spaces in the line) + std::string::size_type nextPos = _Text.find_first_not_of((ucchar) ' ', charIndex); + if (nextPos != std::string::npos) + { + if (getLineFromIndex(charIndex) == (sint) line) + { + return (sint) nextPos; + } + } + return charIndex; + } + + // *************************************************************************** + void CViewText::getLineEndIndex(uint line, sint &index, bool &endOfPreviousLine) const + { + sint startIndex = getLineStartIndex(line); + if (startIndex == -1) + { + index = -1; + endOfPreviousLine = false; + return; + } + index = startIndex + _Lines[line]->getNumChars() + _Lines[line]->getEndSpaces(); + endOfPreviousLine = !_Lines[line]->getLF(); + } + + // *************************************************************************** + void CViewText::setHardText (const std::string &ht) + { + // ucstring Text = ucstring(ht); + ucstring Text; + if ((ht.size()>2) && (ht[0] == 'u') && (ht[1] == 'i')) + Text = CI18N::get (ht); + else + Text.fromUtf8(ht); + setText(Text); + } + + // *************************************************************************** + string CViewText::getColorAsString() const + { + return NLMISC::toString(_Color.R) + " " + NLMISC::toString(_Color.G) + " " + NLMISC::toString(_Color.B) + " " + NLMISC::toString(_Color.A); + } + + // *************************************************************************** + void CViewText::setColorAsString(const string &ht) + { + _Color = convertColor (ht.c_str()); + } + + // *************************************************************************** + NLMISC::CRGBA CViewText::getColorRGBA() const + { + return _Color; + } + + // *************************************************************************** + void CViewText::setColorRGBA(NLMISC::CRGBA col) + { + _Color = col; + } + + // *************************************************************************** + void CViewText::getCharacterPositionFromIndex(sint index, bool cursorAtPreviousLineEnd, sint &x, sint &y, sint &height) const + { + NLMISC::clamp(index, 0, (sint) _Text.length()); + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + TextContext->setHotSpot (UTextContext::BottomLeft); + TextContext->setShaded (_Shadow); + TextContext->setFontSize (_FontSize); + // CViewRenderer &rVR = *CViewRenderer::getInstance(); + height = getFontHeight(); + // + if (_MultiLine) + { + uint charIndex = 0; + // special case for end of text + if (index == (sint) _Text.length()) + { + y = 0; + if (_Lines.empty()) + { + x = 0; + } + else + { + CLine &lastLine = *_Lines.back(); + x = (sint) (lastLine.getWidth() + lastLine.getEndSpaces() * lastLine.getSpaceWidth()); + sint nMaxWidth = getCurrentMultiLineMaxW(); + x = std::min(x, nMaxWidth); + } + return; + } + for(sint i = 0; i < (sint) _Lines.size(); ++i) + { + if (i != 0 && charIndex == (uint) index && cursorAtPreviousLineEnd) + { + // should display the character at the end of previous line + CLine &currLine = *_Lines[i - 1]; + y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - i)); + x = (sint) (currLine.getWidth() + currLine.getEndSpaces() * currLine.getSpaceWidth()); + sint nMaxWidth = getCurrentMultiLineMaxW(); + x = std::min(x, nMaxWidth); + return; + } + CLine &currLine = *_Lines[i]; + uint newCharIndex = charIndex + currLine.getNumChars() + currLine.getEndSpaces() + (_Lines[i]->getLF() ? 1 : 0); + if ((sint) newCharIndex > index) + { + // ok, this line contains the character, now, see which word contains it. + y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - 1 - i)); + // see if the index is in the spaces at the end of line + if (index - charIndex >= currLine.getNumChars()) + { + uint numSpaces = index - charIndex - currLine.getNumChars(); + x = (sint) (currLine.getWidth() + numSpaces * _SpaceWidth); + sint nMaxWidth = getCurrentMultiLineMaxW(); + x = std::min(x, nMaxWidth); + return; + } + // now, search containing word in current line + float px = (float)_FirstLineX; + for(uint k = 0; k < currLine.getNumWords(); ++k) + { + CWord &currWord = currLine.getWord(k); + if ((sint) (charIndex + currWord.NumSpaces + currWord.Text.length()) >= index) + { + // character is in currWord or the in spaces preceding it + // check if the character is in the word + if ((uint) (index - charIndex) > currWord.NumSpaces) + { + // get the x position + ucstring subStr = currWord.Text.substr(0, index - charIndex - currWord.NumSpaces); + // compute the size + UTextContext::CStringInfo si = TextContext->getStringInfo(subStr); + x = (sint) (px + si.StringWidth + currWord.NumSpaces * currLine.getSpaceWidth()); + height = getFontHeight(); + return; + } + else + { + // character is in the spaces preceding the word + x = (sint) (px + currLine.getSpaceWidth() * (index - charIndex)); + height = getFontHeight(); + return; + } + } + charIndex += (uint)currWord.Text.length() + currWord.NumSpaces; + px += currWord.NumSpaces * currLine.getSpaceWidth() + currWord.Info.StringWidth; + } + } + charIndex = newCharIndex; + } + + } + else + { + // get the x position + ucstring subStr = _Text.substr(0, index); + // compute the size + UTextContext::CStringInfo si = TextContext->getStringInfo(subStr); + y = 0; + x = (sint) si.StringWidth; + } + } + + // *************************************************************************** + // Tool fct : From a word and a x coordinate, give the matching character index + static uint getCharacterIndex(const ucstring &textValue, float x) + { + float px = 0.f; + UTextContext::CStringInfo si; + ucstring singleChar(" "); + uint i; + for (i = 0; i < textValue.length(); ++i) + { + // get character width + singleChar[0] = textValue[i]; + si = CViewRenderer::getTextContext()->getStringInfo(singleChar); + px += si.StringWidth; + // the character is at the i - 1 position + if (px > x) + { + // if the half of the character is after the cursor, then prefer select the next one (like in Word) + if(px-si.StringWidth/2 < x) + i++; + break; + } + } + return i; + } + + // *************************************************************************** + void CViewText::getCharacterIndexFromPosition(sint x, sint y, uint &index, bool &cursorAtPreviousLineEnd) const + { + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + + // setup the text context + TextContext->setHotSpot (UTextContext::BottomLeft); + TextContext->setShaded (_Shadow); + TextContext->setFontSize (_FontSize); + // find the line where the character is + // CViewRenderer &rVR = *CViewRenderer::getInstance(); + uint charPos = 0; + if (_MultiLine) + { + // seek the line + float py = 0.f; + if (py > y) + { + index = (uint)_Text.length(); + cursorAtPreviousLineEnd = false; + return; + } + sint line; + for (line = (uint)_Lines.size() - 1; line >= 0; --line) + { + float newPy = py + _FontHeight + _MultiLineSpace; + if (newPy > y) + { + break; + } + py = newPy; + } + if (line == -1) + { + index = 0; + cursorAtPreviousLineEnd = false; + return; // above the first line, so take character 0 + } + // compute character index at start of line + sint i; + for (i = 0; i < line; ++i) + { + charPos += _Lines[i]->getNumChars() + _Lines[i]->getEndSpaces() + (_Lines[i]->getLF() ? 1 : 0); + } + // seek word that contains the character + CLine &currLine = *_Lines[line]; + // See if character is in the ending spaces + if (x >= (sint) currLine.getWidth()) + { + // Add _SpaceWidth/2 to select between chars + sint numSpaces = _SpaceWidth != 0 ? (sint) (((float) x + _SpaceWidth/2 - currLine.getWidth()) / _SpaceWidth) + : 0; + clamp(numSpaces, 0, (sint)currLine.getEndSpaces()); + index = charPos + currLine.getNumChars() + numSpaces; + cursorAtPreviousLineEnd = !_Lines[i]->getLF(); + return; + } + + float px = (float)_FirstLineX; + for(uint k = 0; k < currLine.getNumWords(); ++k) + { + CWord &currWord = currLine.getWord(k); + float spacesWidth = currLine.getSpaceWidth() * currWord.NumSpaces; + float newPx = px + currWord.Info.StringWidth + spacesWidth; + if (newPx >= x) // if the word contains the x position.. + { + if (x < (px + spacesWidth)) + { + // the coords x is in the spaces that are preceding the word + // Add spaceWidth/2 to select between chars + sint numSpaces = currLine.getSpaceWidth() != 0 ? (sint) ((x + currLine.getSpaceWidth()/2 - px) / currLine.getSpaceWidth()) + : 0; + clamp(numSpaces, 0, (sint)currWord.NumSpaces); + index = numSpaces + charPos; + cursorAtPreviousLineEnd = false; + return; + } + else + { + // the coord is in the word itself + index = charPos + currWord.NumSpaces + getCharacterIndex(currWord.Text, (float) x - (px + spacesWidth)); + cursorAtPreviousLineEnd = false; + return; + } + } + px = newPx; + charPos += (uint)currWord.Text.length() + currWord.NumSpaces; + } + index = charPos; + cursorAtPreviousLineEnd = false; + return; + } + else + { + cursorAtPreviousLineEnd = false; + if (y < 0) + { + index = (uint)_Text.length(); + return; + } + if (y > (sint) _FontHeight) + { + index = 0; + return; + } + index = getCharacterIndex(_Text, (float) x); + return; + } + } + + // *************************************************************************** + void CViewText::enableStringSelection(uint start, uint end) + { + _TextSelection= true; + _TextSelectionStart= start; + _TextSelectionEnd= end; + } + + // *************************************************************************** + void CViewText::disableStringSelection() + { + _TextSelection= false; + _TextSelectionStart= 0; + _TextSelectionEnd= std::numeric_limits::max(); + } + + // *************************************************************************** + void CViewText::setStringSelectionSkipingSpace(uint stringId, const ucstring &text, sint charStart, sint charEnd) + { + sint quadStart= charStart; + sint quadSize= charEnd-charStart; + sint j; + for(j=0;jsetStringSelection(stringId, quadStart, quadSize); + } + + // *************************************************************************** + void CViewText::clearLines() + { + for(uint k = 0; k < _Lines.size(); ++k) + { + _Lines[k]->clear(); + } + _Lines.clear(); + } + + // *************************************************************************** + uint CViewText::getNumLine() const + { + if (_MultiLine) + { + return (uint)_Lines.size(); + } + else + { + return _Text.empty() ? 0 : 1; + } + } + + // *************************************************************************** + uint CViewText::getFirstLineX() const + { + return _FirstLineX; + } + + // *************************************************************************** + uint CViewText::getLastLineW () const + { + if (!_Lines.empty()) + return (uint)_Lines.back()->getWidth(); + return 0; + } + + // *************************************************************************** + void CViewText::setFirstLineX(uint firstLineX) + { + _FirstLineX = firstLineX; + } + + ///////////////////////////////////// + // CViewText::CLine implementation // + ///////////////////////////////////// + + // *************************************************************************** + CViewText::CLine::CLine() : _NumChars(0), + _NumSpaces(0), + _SpaceWidth(0.f), + _StringLine(0), + _WidthWithoutSpaces(0.f), + _EndSpaces(0), + _HasLF(false) + { + } + + // *************************************************************************** + void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, uint fontWidth) + { + CWord word; + word.build(text, numSpaces); + word.Format= wordFormat; + addWord(word, fontWidth); + } + + // *************************************************************************** + void CViewText::CLine::addWord(const CWord &word, uint fontWidth) + { + _Words.push_back(word); + _NumChars += word.NumSpaces + uint(word.Text.length()); + _NumSpaces += word.NumSpaces; + if (fabsf(word.Info.StringLine) > fabsf(_StringLine)) + { + _StringLine = word.Info.StringLine; + } + // the width of the line must reach at least the Tab + _WidthWithoutSpaces= max(_WidthWithoutSpaces, word.Format.TabX * float(fontWidth)); + // append the text space + _WidthWithoutSpaces += word.Info.StringWidth; + } + + // *************************************************************************** + void CViewText::CLine::clear() + { + for(uint k = 0; k < _Words.size(); ++k) + { + if (_Words[k].Index != 0xffffffff) + CViewRenderer::getTextContext()->erase(_Words[k].Index); + } + _Words.clear(); + _NumChars = 0; + _SpaceWidth = 0.f; + } + + // *************************************************************************** + void CViewText::CLine::resetTextIndex() + { + for(uint k = 0; k < _Words.size(); ++k) + { + _Words[k].Index = 0xffffffff; + } + } + + // *************************************************************************** + void CViewText::CWord::build(const ucstring &text, uint numSpaces/*=0*/) + { + Text = text; + NumSpaces = numSpaces; + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + Index = TextContext->textPush(text); + Info = TextContext->getStringInfo(Index); + } + + // *************************************************************************** + void CViewText::removeEndSpaces() + { + sint i = (sint)_Text.size()-1; + while ((i>=0) && ((_Text[i] < 0x20) || (_Text[i] == ' '))) + { + i--; + } + _Text.resize (i+1); + } + + // *************************************************************************** + sint32 CViewText::getMaxUsedW() const + { + static const ucstring spaceStr(" \t"); + static const ucstring lineFeedStr("\n"); + float maxWidth = 0; + + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + TextContext->setHotSpot (UTextContext::BottomLeft); + TextContext->setShaded (_Shadow); + TextContext->setFontSize (_FontSize); + + TCharPos linePos = 0; + while (linePos < _Text.length()) + { + // Get the end of the line + float lineWidth = 0; + TCharPos lineEnd; + lineEnd = _Text.find_first_of(lineFeedStr, linePos); + if (lineEnd == std::string::npos) + { + lineEnd = _Text.length(); + } + + ucstring lineValue; + lineValue = _Text.substr(linePos, lineEnd - linePos); + + TCharPos currPos = 0; + while (currPos != lineValue.length()) + { + TCharPos spaceEnd; + TCharPos wordEnd; + uint numSpaces; + + // Skip spaces and count them + spaceEnd = lineValue.find_first_not_of(spaceStr, currPos); + if (spaceEnd == std::string::npos) + { + spaceEnd = lineValue.length(); + } + numSpaces = (uint) (spaceEnd - currPos); + + // Get word until a space or a \n is encountered + wordEnd = lineValue.find_first_of(spaceStr, spaceEnd); + if (wordEnd == std::string::npos) + { + wordEnd = lineValue.length(); + } + + ucstring wordValue; + wordValue = lineValue.substr(spaceEnd, wordEnd - spaceEnd); + + // compute width of word + UTextContext::CStringInfo si; + si = TextContext->getStringInfo(wordValue); + + // compute size of spaces + word + lineWidth += numSpaces * _SpaceWidth + si.StringWidth; + + currPos = wordEnd; + } + + // Update line width + if (lineWidth > maxWidth) + maxWidth = lineWidth; + + linePos = lineEnd+1; + } + + return (sint32)maxWidth; + } + + // *************************************************************************** + sint32 CViewText::getMinUsedW() const + { + static const ucstring spaceOrLineFeedStr(" \n\t"); + sint32 maxWidth = 0; + + // Not multi line ? Same size than min + if (!_MultiLine) + return getMaxUsedW(); + + // If we can clip word, size of the largest word + if (_TextMode == ClipWord) + { + // No largest font parameter, return the font height + return _FontHeight; + } + // If we can't clip the words, return the size of the largest word + else if ((_TextMode == DontClipWord) || (_TextMode == Justified)) + { + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + TextContext->setHotSpot (UTextContext::BottomLeft); + TextContext->setShaded (_Shadow); + TextContext->setFontSize (_FontSize); + + // Current position in text + TCharPos currPos = 0; + while (currPos < _Text.length()) + { + // Current word + ucstring wordValue; + UTextContext::CStringInfo si; + TCharPos wordEnd; + + // Get word until a space or a \n is encountered + currPos = _Text.find_first_not_of(spaceOrLineFeedStr, currPos); + if (currPos == std::string::npos) + break; + wordEnd = _Text.find_first_of(spaceOrLineFeedStr, currPos); + if (wordEnd == std::string::npos) + wordEnd = _Text.length(); + + // Get the word + wordValue = _Text.substr(currPos, wordEnd - currPos); + + // Compute width of word + si = TextContext->getStringInfo(wordValue); + + // Larger ? + sint32 stringWidth = (sint32)si.StringWidth; + if (stringWidth>maxWidth) + maxWidth = stringWidth; + + // Next word + currPos = wordEnd; + } + } + + return maxWidth; + } + + // *************************************************************************** + void CViewText::onInvalidateContent() + { + _InvalidTextContext= true; + invalidateCoords(); + } + + // *************************************************************************** + void CViewText::computeFontSize () + { + NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); + TextContext->setHotSpot (UTextContext::BottomLeft); + TextContext->setShaded (_Shadow); + TextContext->setFontSize (_FontSize); + + // Letter size + UTextContext::CStringInfo si = TextContext->getStringInfo(ucstring("|")); // for now we can't now that directly from UTextContext + _FontHeight = (uint) si.StringHeight + (_Shadow?1:0); + _FontLegHeight = (uint) si.StringLine + (_Shadow?1:0); + + // Space width + si = TextContext->getStringInfo(ucstring(" ")); + _SpaceWidth = si.StringWidth; + + // Font Width + si = TextContext->getStringInfo(ucstring("_")); + _FontWidth = (uint)si.StringWidth; + } + + + // *************************************************************************** + static inline bool isColorTag(const ucstring &s, uint index, uint textSize) + { + // Format is @{RGBA} + if(s[index]=='@') + { + if( textSize>index+1 && s[index+1]=='{') + { + // verify 1st letter is a xdigit + if( textSize>index+2 && isxdigit(s[index+2])) + { + // We have good chance its a color tag. Do last verification + if(textSize>index+6 && s[index+6]=='}') + { + return true; + } + } + } + } + + return false; + } + + // *************************************************************************** + // isColorTag must be ok. + static inline CRGBA getColorTag(const ucstring &s, uint &index) + { + // extract the color string: "FABC" + char tmpCol[5]; + for(uint i=0;i<4;i++) + tmpCol[i]= (char)s[index+2+i]; + tmpCol[4]= 0; + + // Convert to color + CRGBA color; + uint pCol; + sscanf(tmpCol, "%x", &pCol); + // Transform 4 bits to 8 bit. + color.R= (pCol>>12)&0xF; color.R+= color.R<<4; + color.G= (pCol>>8)&0xF; color.G+= color.G<<4; + color.B= (pCol>>4)&0xF; color.B+= color.B<<4; + color.A= (pCol)&0xF; color.A+= color.A<<4; + + // skip tag + index+= 7; + + return color; + } + + + // *************************************************************************** + const uint MaxTabDigit= 3; + static inline bool isTabTag(const ucstring &s, uint index, uint textSize) + { + // Format is @{Tvalue}, where value ,1,2,3 digit. + if(s[index]=='@') + { + if( textSize>index+1 && s[index+1]=='{') + { + if( textSize>index+2 && s[index+2]=='T') + { + // We have good chance its a Tab tag. Do last verification + for(uint i=4;i<4+MaxTabDigit;i++) + { + if(textSize>index+i && s[index+i]=='}') + { + return true; + } + } + } + } + } + + return false; + } + + // *************************************************************************** + // isTabTag must be ok. + static inline sint getTabTag(const ucstring &s, uint &index) + { + // extract the tab min X value + char tmpTab[MaxTabDigit+1]; + uint i; + for(i=0;iindex+1 && s[index+1]=='{') + { + if( textSize>index+2 && s[index+2]=='H') + { + uint i = 3; + while (textSize>index+i && s[index+i]!='}') + i++; + + if (textSize>index+i && s[index+i]=='}') + return true; + } + } + } + + return false; + } + + // *************************************************************************** + // isTooltipTag must be ok. + static inline ucstring getTooltipTag(const ucstring &s, uint &index) + { + ucstring result; + uint i = 3; + while (s[index+i] != '}') + { + result += s[index+i]; + i++; + } + + // skip tag + index += i+1; + + return result; + } + + + // *************************************************************************** + void CViewText::buildFormatTagText(const ucstring &text, ucstring &textBuild, std::vector &formatTags, std::vector &tooltips) + { + formatTags.clear(); + tooltips.clear(); + + // Build the text without the formatTags, and get the color tags separately + textBuild.reserve(text.size()); + uint textSize= (uint)text.size(); + // Must herit all the props from old tags. + CViewText::CFormatTag precTag; // set default. + precTag.Index = 0; + for (uint i = 0; i < textSize;) + { + if(isColorTag(text, i, textSize)) + { + // get old tag. + CViewText::CFormatTag ct= precTag; + // get new color and skip tag. + ct.Color= getColorTag(text, i); + ct.Index= (uint)textBuild.size(); + formatTags.push_back(ct); + } + else if(isTabTag(text, i, textSize)) + { + // get old tag. + CViewText::CFormatTag ct= precTag; + // get new Tab and skip tag. + ct.TabX= getTabTag(text, i); + ct.Index= (uint)textBuild.size(); + formatTags.push_back(ct); + } + else if(isTooltipTag(text, i, textSize)) + { + // get old tag. + CViewText::CFormatTag ct= precTag; + // get new Tab and skip tag. + ucstring uitt = getTooltipTag(text, i); + if (uitt.empty()) + { + ct.IndexTt= -1; + } + else + { + ct.IndexTt= (uint)tooltips.size(); + tooltips.push_back(uitt); + } + + ct.Index= (uint)textBuild.size(); + formatTags.push_back(ct); + } + else + { + bool lineFeed= text[i]=='\n'; + + // append to textBuild + textBuild+= text[i]; + ++i; + + // if \n, reset tabulations + if(lineFeed) + { + CViewText::CFormatTag ct= precTag; + ct.TabX= 0; + ct.Index= (uint)textBuild.size(); + formatTags.push_back(ct); + } + } + // bkup + if(!formatTags.empty()) + precTag= formatTags.back(); + } + } + + + // *************************************************************************** + void CViewText::setTextFormatTaged(const ucstring &text) + { + + // to allow cache (avoid infinite recurse in updateCoords() in some case), compute in temp + ucstring tempText; + // static to avoid reallocation + static std::vector tempFormatTags; + static std::vector tempTooltips; + buildFormatTagText(text, tempText, tempFormatTags, tempTooltips); + setCase (tempText, _CaseMode); + + // compare Tag arrays + bool sameTagArray= false; + if(_FormatTags.size()==tempFormatTags.size()) + { + sameTagArray= true; + for(uint i=0;i<_FormatTags.size();i++) + { + if(!_FormatTags[i].sameTag(tempFormatTags[i])) + { + sameTagArray= false; + break; + } + } + } + + // test transformed text with current one + if(tempText!=_Text || !sameTagArray ) + { + // copy tags + _FormatTags= tempFormatTags; + // Copy to Text (preserve Memory) + contReset(_Text); + _Text= tempText; + + CInterfaceGroup *parent = getParent(); + + // Delete old dynamic tooltips + for (uint i=0 ; i<_Tooltips.size() ; ++i) + { + if (parent) + parent->delCtrl(_Tooltips[i]); + else + delete _Tooltips[i]; + } + _Tooltips.clear(); + + // Add new dynamic tooltips + for (uint i=0 ; isetId(_Id+"_tt"+toString(i)); + pTooltip->setAvoidResizeParent(avoidResizeParent()); + pTooltip->setRenderLayer(getRenderLayer()); + pTooltip->setDefaultContextHelp(CI18N::get(tempTooltips[i].toString())); + pTooltip->setParentPos(this); + pTooltip->setParentPosRef(Hotspot_BR); + pTooltip->setPosRef(Hotspot_BR); + pTooltip->setToolTipParent(CCtrlBase::TTWindow); + pTooltip->setToolTipParentPosRef(Hotspot_TTAuto); + pTooltip->setToolTipPosRef(Hotspot_TTAuto); + pTooltip->setActive(true); + + _Tooltips.push_back(pTooltip); + + if (parent) + { + pTooltip->setParent(parent); + parent->addCtrl(_Tooltips.back()); + } + } + + if (parent) + _Setuped = true; + else + _Setuped = false; + + invalidateContent (); + } + + // color format is available only if multilined + if (!_MultiLine) + nlwarning( toString("ViewText isn't multilined : uc_hardtext_format will not act as wanted !\n%s", text.toString().c_str()).c_str() ); + } + + + void CViewText::setSingleLineTextFormatTaged(const ucstring &text) + { + // to allow cache (avoid infinite recurse in updateCoords() in some case), compute in temp + ucstring tempText; + static std::vector tempLetterColors; + static std::vector tempTooltips; + + // parse text + buildFormatTagText(text, tempText, tempLetterColors, tempTooltips); + setCase (tempText, _CaseMode); + + // decal for spaces (not inserted in VertexBuffer) + uint textIndex = 0; + uint spacesNb = 0; + for(uint i=0; icreateLetterColors(); + for(uint i=0; ipushLetterColor(formatTag.Index, formatTag.Color); + } + + // test transformed text with current one + if(tempText!=_Text || !_LetterColors || !_LetterColors->isSameLetterColors(letterColors)) + { + _LetterColors = letterColors; + + TextContext->setLetterColors(letterColors, _Index); + + // Copy to Text (preserve Memory) + contReset(_Text); + _Text= tempText; + invalidateContent (); + } + + // this color format is available only if not multilined + if (_MultiLine) + nlwarning( toString("ViewText is multilined : uc_hardtext_single_line_format will not act as wanted !\n%s", text.toString().c_str()).c_str() ); + } + + + // *************************************************************************** + bool CViewText::isFormatTagChange(uint textIndex, uint ctIndex) const + { + if(ctIndex>=_FormatTags.size()) + return false; + // return true if the textIndex is > (eg if some skip with spaces) or = (common case) + return _FormatTags[ctIndex].Index <= textIndex; + } + + // *************************************************************************** + void CViewText::getFormatTagChange(uint textIndex, uint &ctIndex, CFormatInfo &wordFormat) const + { + // support the possible case with multiple color tags with same textIndex. + while(ctIndex<_FormatTags.size() && _FormatTags[ctIndex].Index<=textIndex) + { + // Take the last tag. + wordFormat.Color= _FormatTags[ctIndex].Color; + wordFormat.TabX= _FormatTags[ctIndex].TabX; + wordFormat.IndexTt= _FormatTags[ctIndex].IndexTt; + // skip it. + ctIndex++; + } + } + + + // *************************************************************************** + + void CViewText::setCaseMode (TCaseMode caseMode) + { + _CaseMode = caseMode; + setCase (_Text, _CaseMode); + } + + // *************************************************************************** + + TCaseMode CViewText::getCaseMode () const + { + return _CaseMode; + } + + // *************************************************************************** + + void CViewText::resetTextIndex() + { + _Index = 0xffffffff; + for(uint k = 0; k < _Lines.size(); ++k) + _Lines[k]->resetTextIndex(); + } + + // *************************************************************************** + void CViewText::setup() + { + _Setuped= true; + + // Add dynamic tooltips + for (uint i=0 ; i<_Tooltips.size() ; ++i) + { + CInterfaceGroup *parent = getParent(); + if (parent) + { + _Tooltips[i]->setParent(parent); + parent->addCtrl(_Tooltips.back()); + } + } + } + + // *************************************************************************** + void CViewText::serial(NLMISC::IStream &f) + { + #define SERIAL_UINT(val) { uint32 tmp = (uint32) val; f.serial(tmp); val = (uint) tmp; } + #define SERIAL_SINT(val) { sint32 tmp = (sint32) val; f.serial(tmp); val = (sint) tmp; } + CViewBase::serial(f); + SERIAL_SINT(_FontSize); + SERIAL_UINT(_FontWidth); + SERIAL_UINT(_FontHeight); + SERIAL_UINT(_FontLegHeight); + f.serial(_SpaceWidth); + f.serial(_Color); + f.serial(_Shadow); + f.serialEnum(_CaseMode); + f.serial(_ShadowColor); + f.serial(_LineMaxW); + f.serial(_SingleLineTextClamped); + f.serial(_MultiLine); + f.serial(_MultiLineMaxWOnly); + f.serial(_MultiLineClipEndSpace); + f.serial(_AutoClampOffset); + f.serialEnum(_TextMode); + SERIAL_SINT(_MultiLineSpace); + SERIAL_SINT(_LastMultiLineMaxW); + f.serial(_MultiMaxLine); + + bool hasTag = !_FormatTags.empty(); + f.serial(hasTag); + if (f.isReading()) + { + ucstring text; + f.serial(text); + if (hasTag) + { + if (_MultiLine) + { + setTextFormatTaged(text); + } + else + { + setSingleLineTextFormatTaged(text); + } + } + else + { + setText(text); + } + } + else + { + f.serial(_Text); + } + + #undef SERIAL_UINT + #undef SERIAL_SINT + } + + + // *************************************************************************** + +} + diff --git a/code/ryzom/client/src/interface_v3/chat_text_manager.cpp b/code/ryzom/client/src/interface_v3/chat_text_manager.cpp index 8bf79b805..3b212af7e 100644 --- a/code/ryzom/client/src/interface_v3/chat_text_manager.cpp +++ b/code/ryzom/client/src/interface_v3/chat_text_manager.cpp @@ -19,7 +19,7 @@ #include "stdpch.h" // client #include "chat_text_manager.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "interface_manager.h" using namespace std; diff --git a/code/ryzom/client/src/interface_v3/chat_window.h b/code/ryzom/client/src/interface_v3/chat_window.h index 8e5da91c2..285116998 100644 --- a/code/ryzom/client/src/interface_v3/chat_window.h +++ b/code/ryzom/client/src/interface_v3/chat_window.h @@ -28,12 +28,12 @@ namespace NLGUI { class CCtrlBase; + class CViewText; } class CChatWindow; class CGroupContainer; class CGroupEditBox; -class CViewText; /** Interface to react to a chat box entry * Derivers should define the msgEntered member function to handle entry event. diff --git a/code/ryzom/client/src/interface_v3/ctrl_text_button.cpp b/code/ryzom/client/src/interface_v3/ctrl_text_button.cpp index efa54d33c..62a82831b 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_text_button.cpp +++ b/code/ryzom/client/src/interface_v3/ctrl_text_button.cpp @@ -23,7 +23,7 @@ #include "ctrl_text_button.h" #include "interface_manager.h" #include "nel/misc/xml_auto_ptr.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "view_text_id.h" #include "group_container.h" #include "nel/gui/lua_ihm.h" diff --git a/code/ryzom/client/src/interface_v3/ctrl_text_button.h b/code/ryzom/client/src/interface_v3/ctrl_text_button.h index 34a93520e..fd90e2d7e 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_text_button.h +++ b/code/ryzom/client/src/interface_v3/ctrl_text_button.h @@ -26,10 +26,9 @@ namespace NLGUI { class CEventDescriptor; + class CViewText; } class CInterfaceManager; -class CViewText; - // *************************************************************************** /** diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp index c02b21caf..3f1e81378 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp @@ -20,7 +20,7 @@ #include "dbctrl_sheet.h" #include "interface_manager.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "../sheet_manager.h" #include "../client_sheets/entity_sheet.h" #include "../client_sheets/pact_sheet.h" diff --git a/code/ryzom/client/src/interface_v3/dbgroup_build_phrase.cpp b/code/ryzom/client/src/interface_v3/dbgroup_build_phrase.cpp index 521fd3605..bfe7e06fe 100644 --- a/code/ryzom/client/src/interface_v3/dbgroup_build_phrase.cpp +++ b/code/ryzom/client/src/interface_v3/dbgroup_build_phrase.cpp @@ -26,7 +26,7 @@ #include "nel/gui/ctrl_button.h" #include "group_editbox.h" #include "../client_cfg.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "skill_manager.h" #include "../string_manager_client.h" diff --git a/code/ryzom/client/src/interface_v3/dbgroup_build_phrase.h b/code/ryzom/client/src/interface_v3/dbgroup_build_phrase.h index 75a162dd5..94af94de9 100644 --- a/code/ryzom/client/src/interface_v3/dbgroup_build_phrase.h +++ b/code/ryzom/client/src/interface_v3/dbgroup_build_phrase.h @@ -29,6 +29,7 @@ namespace NLGUI { class CCtrlBaseButton; + class CViewText; } @@ -36,7 +37,6 @@ namespace NLGUI class CDBCtrlSheet; class CSBrickSheet; class CViewBitmap; -class CViewText; class CGroupEditBox; diff --git a/code/ryzom/client/src/interface_v3/dbgroup_combo_box.h b/code/ryzom/client/src/interface_v3/dbgroup_combo_box.h index 90e1a2036..4429c6a13 100644 --- a/code/ryzom/client/src/interface_v3/dbgroup_combo_box.h +++ b/code/ryzom/client/src/interface_v3/dbgroup_combo_box.h @@ -25,10 +25,10 @@ namespace NLGUI { class CCtrlBaseButton; + class CViewText; } // *************************************************************************** -class CViewText; class CGroupMenu; // *************************************************************************** diff --git a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.cpp b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.cpp index b76ef53fb..fd98d08b9 100644 --- a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.cpp +++ b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.cpp @@ -23,7 +23,7 @@ #include "nel/misc/xml_auto_ptr.h" #include "../sheet_manager.h" #include "nel/gui/ctrl_button.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "nel/gui/action_handler.h" #include "../time_client.h" #include "game_share/animal_status.h" diff --git a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.h b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.h index f11faabbf..f5d5fdb67 100644 --- a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.h +++ b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.h @@ -25,7 +25,7 @@ #include "nel/misc/types_nl.h" #include "list_sheet_base.h" #include "dbctrl_sheet.h" -#include "view_text.h" +#include "nel/gui/view_text.h" namespace NLGUI { diff --git a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_trade.cpp b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_trade.cpp index defdeff6c..de7711f69 100644 --- a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_trade.cpp +++ b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_trade.cpp @@ -23,7 +23,7 @@ #include "nel/misc/xml_auto_ptr.h" #include "../sheet_manager.h" #include "nel/gui/ctrl_button.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "nel/gui/action_handler.h" #include "sphrase_manager.h" #include "game_share/time_weather_season/time_and_season.h" diff --git a/code/ryzom/client/src/interface_v3/dbgroup_select_number.cpp b/code/ryzom/client/src/interface_v3/dbgroup_select_number.cpp index 02e44236e..4889fa367 100644 --- a/code/ryzom/client/src/interface_v3/dbgroup_select_number.cpp +++ b/code/ryzom/client/src/interface_v3/dbgroup_select_number.cpp @@ -21,7 +21,7 @@ #include "dbgroup_select_number.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "view_bitmap.h" #include "nel/gui/ctrl_button.h" #include "nel/gui/interface_property.h" diff --git a/code/ryzom/client/src/interface_v3/dbgroup_select_number.h b/code/ryzom/client/src/interface_v3/dbgroup_select_number.h index a02708e87..d6446ee33 100644 --- a/code/ryzom/client/src/interface_v3/dbgroup_select_number.h +++ b/code/ryzom/client/src/interface_v3/dbgroup_select_number.h @@ -26,12 +26,12 @@ namespace NLGUI { class CCtrlBaseButton; + class CViewText; } // *************************************************************************** class CViewBitmap; -class CViewText; // *************************************************************************** diff --git a/code/ryzom/client/src/interface_v3/dbview_number.h b/code/ryzom/client/src/interface_v3/dbview_number.h index 1c7079f06..602f0e3b9 100644 --- a/code/ryzom/client/src/interface_v3/dbview_number.h +++ b/code/ryzom/client/src/interface_v3/dbview_number.h @@ -21,7 +21,7 @@ #include "nel/misc/types_nl.h" -#include "view_text.h" +#include "nel/gui/view_text.h" // *************************************************************************** diff --git a/code/ryzom/client/src/interface_v3/dbview_quantity.h b/code/ryzom/client/src/interface_v3/dbview_quantity.h index 65a12086d..a693a46d3 100644 --- a/code/ryzom/client/src/interface_v3/dbview_quantity.h +++ b/code/ryzom/client/src/interface_v3/dbview_quantity.h @@ -21,7 +21,7 @@ #include "nel/misc/types_nl.h" -#include "view_text.h" +#include "nel/gui/view_text.h" // *************************************************************************** diff --git a/code/ryzom/client/src/interface_v3/flying_text_manager.cpp b/code/ryzom/client/src/interface_v3/flying_text_manager.cpp index f8ef9e29c..54b910564 100644 --- a/code/ryzom/client/src/interface_v3/flying_text_manager.cpp +++ b/code/ryzom/client/src/interface_v3/flying_text_manager.cpp @@ -20,7 +20,7 @@ #include "flying_text_manager.h" #include "interface_manager.h" #include "group_in_scene.h" -#include "view_text.h" +#include "nel/gui/view_text.h" using namespace std; diff --git a/code/ryzom/client/src/interface_v3/group_container.cpp b/code/ryzom/client/src/interface_v3/group_container.cpp index ee6379722..c1efb9c0d 100644 --- a/code/ryzom/client/src/interface_v3/group_container.cpp +++ b/code/ryzom/client/src/interface_v3/group_container.cpp @@ -34,7 +34,7 @@ #include "group_list.h" #include "nel/gui/ctrl_button.h" #include "nel/gui/ctrl_scroll.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "view_bitmap.h" #include "../time_client.h" diff --git a/code/ryzom/client/src/interface_v3/group_container.h b/code/ryzom/client/src/interface_v3/group_container.h index 0a79f0931..35c5a851e 100644 --- a/code/ryzom/client/src/interface_v3/group_container.h +++ b/code/ryzom/client/src/interface_v3/group_container.h @@ -28,10 +28,10 @@ namespace NLGUI class CEventDescriptorLocalised; class CCtrlButton; class CCtrlScroll; + class CViewText; } class CInterfaceList; -class CViewText; class COptionsContainerInsertion; class COptionsContainerMove; class CGroupContainer; diff --git a/code/ryzom/client/src/interface_v3/group_editbox.cpp b/code/ryzom/client/src/interface_v3/group_editbox.cpp index 7d51be171..529642288 100644 --- a/code/ryzom/client/src/interface_v3/group_editbox.cpp +++ b/code/ryzom/client/src/interface_v3/group_editbox.cpp @@ -22,7 +22,7 @@ #include "interface_manager.h" #include "input_handler_manager.h" #include "nel/misc/command.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "nel/misc/xml_auto_ptr.h" #include "nel/gui/interface_options.h" #include "dbctrl_sheet.h" diff --git a/code/ryzom/client/src/interface_v3/group_editbox.h b/code/ryzom/client/src/interface_v3/group_editbox.h index 99a07c093..1c0a02e68 100644 --- a/code/ryzom/client/src/interface_v3/group_editbox.h +++ b/code/ryzom/client/src/interface_v3/group_editbox.h @@ -26,8 +26,8 @@ namespace NLGUI { class CEventDescriptor; + class CViewText; } -class CViewText; // ---------------------------------------------------------------------------- class CGroupEditBox : public CGroupEditBoxBase diff --git a/code/ryzom/client/src/interface_v3/group_list.h b/code/ryzom/client/src/interface_v3/group_list.h index b7fe975d2..94b5d5b7f 100644 --- a/code/ryzom/client/src/interface_v3/group_list.h +++ b/code/ryzom/client/src/interface_v3/group_list.h @@ -21,7 +21,7 @@ #include "nel/misc/types_nl.h" #include "nel/gui/group_frame.h" -#include "view_text.h" +#include "nel/gui/view_text.h" // ---------------------------------------------------------------------------- diff --git a/code/ryzom/client/src/interface_v3/group_map.h b/code/ryzom/client/src/interface_v3/group_map.h index d2fa808b7..0521ede20 100644 --- a/code/ryzom/client/src/interface_v3/group_map.h +++ b/code/ryzom/client/src/interface_v3/group_map.h @@ -28,7 +28,7 @@ #include "nel/gui/interface_group.h" #include "nel/gui/ctrl_button.h" #include "view_bitmap.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "animal_position_state.h" #include "../continent.h" // diff --git a/code/ryzom/client/src/interface_v3/group_menu.h b/code/ryzom/client/src/interface_v3/group_menu.h index 41bcae76a..8f87f09a6 100644 --- a/code/ryzom/client/src/interface_v3/group_menu.h +++ b/code/ryzom/client/src/interface_v3/group_menu.h @@ -22,7 +22,7 @@ #include "nel/gui/interface_group.h" #include "nel/gui/group_modal.h" #include "nel/gui/group_submenu_base.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "ctrl_text_button.h" namespace NLGUI diff --git a/code/ryzom/client/src/interface_v3/group_paragraph.h b/code/ryzom/client/src/interface_v3/group_paragraph.h index d73174a90..1366e21a2 100644 --- a/code/ryzom/client/src/interface_v3/group_paragraph.h +++ b/code/ryzom/client/src/interface_v3/group_paragraph.h @@ -21,7 +21,7 @@ #include "nel/misc/types_nl.h" #include "nel/gui/group_frame.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "view_link.h" #include "nel/gui/ctrl_button.h" diff --git a/code/ryzom/client/src/interface_v3/group_phrase_skill_filter.cpp b/code/ryzom/client/src/interface_v3/group_phrase_skill_filter.cpp index 10f23bb9a..4417509a7 100644 --- a/code/ryzom/client/src/interface_v3/group_phrase_skill_filter.cpp +++ b/code/ryzom/client/src/interface_v3/group_phrase_skill_filter.cpp @@ -22,7 +22,7 @@ #include "interface_manager.h" #include "nel/gui/interface_expr.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "game_share/skills.h" #include "game_share/brick_families.h" diff --git a/code/ryzom/client/src/interface_v3/group_scrolltext.cpp b/code/ryzom/client/src/interface_v3/group_scrolltext.cpp index 89e556870..ea8409475 100644 --- a/code/ryzom/client/src/interface_v3/group_scrolltext.cpp +++ b/code/ryzom/client/src/interface_v3/group_scrolltext.cpp @@ -22,7 +22,7 @@ #include "stdpch.h" #include "group_scrolltext.h" #include "group_list.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "nel/gui/ctrl_scroll.h" #include "nel/gui/ctrl_button.h" #include "nel/gui/action_handler.h" diff --git a/code/ryzom/client/src/interface_v3/group_skills.cpp b/code/ryzom/client/src/interface_v3/group_skills.cpp index a4ede0d59..d866a8c5a 100644 --- a/code/ryzom/client/src/interface_v3/group_skills.cpp +++ b/code/ryzom/client/src/interface_v3/group_skills.cpp @@ -23,7 +23,7 @@ #include "interface_manager.h" #include "nel/gui/interface_expr.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "view_bitmap.h" #include "dbview_number.h" #include "dbview_bar.h" diff --git a/code/ryzom/client/src/interface_v3/group_table.h b/code/ryzom/client/src/interface_v3/group_table.h index 7c7ac640e..ba14e7039 100644 --- a/code/ryzom/client/src/interface_v3/group_table.h +++ b/code/ryzom/client/src/interface_v3/group_table.h @@ -21,7 +21,7 @@ #include "nel/misc/types_nl.h" #include "nel/gui/group_frame.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "view_link.h" #include "nel/gui/ctrl_button.h" diff --git a/code/ryzom/client/src/interface_v3/group_tree.cpp b/code/ryzom/client/src/interface_v3/group_tree.cpp index 17c0bff09..4c6d48bb6 100644 --- a/code/ryzom/client/src/interface_v3/group_tree.cpp +++ b/code/ryzom/client/src/interface_v3/group_tree.cpp @@ -22,7 +22,7 @@ #include "interface_manager.h" #include "nel/gui/interface_element.h" #include "view_bitmap.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "group_container.h" #include "nel/gui/action_handler.h" #include "nel/gui/lua_ihm.h" diff --git a/code/ryzom/client/src/interface_v3/group_tree.h b/code/ryzom/client/src/interface_v3/group_tree.h index 038db0cf0..5b158f67b 100644 --- a/code/ryzom/client/src/interface_v3/group_tree.h +++ b/code/ryzom/client/src/interface_v3/group_tree.h @@ -23,8 +23,12 @@ #include "nel/gui/group_frame.h" #include "nel/misc/smart_ptr.h" +namespace NLGUI +{ + class CViewText; +} + class CViewBitmap; -class CViewText; // ---------------------------------------------------------------------------- class CGroupTree : public CInterfaceGroup diff --git a/code/ryzom/client/src/interface_v3/guild_manager.cpp b/code/ryzom/client/src/interface_v3/guild_manager.cpp index ae93f7778..a89387a82 100644 --- a/code/ryzom/client/src/interface_v3/guild_manager.cpp +++ b/code/ryzom/client/src/interface_v3/guild_manager.cpp @@ -22,7 +22,7 @@ #include "interface_manager.h" #include "../string_manager_client.h" #include "nel/gui/action_handler.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "dbctrl_sheet.h" #include "group_container.h" #include "group_menu.h" diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 1e9ebb20e..9624e1074 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -49,7 +49,7 @@ //#include "view_bitmap_progress.h" #include "view_bitmap_faber_mp.h" #include "view_bitmap_combo.h" -#include "view_text.h" +#include "nel/gui/view_text.h" // Ctrl #include "nel/gui/ctrl_scroll.h" #include "nel/gui/ctrl_button.h" diff --git a/code/ryzom/client/src/interface_v3/interface_parser.cpp b/code/ryzom/client/src/interface_v3/interface_parser.cpp index be1f38175..cec1aeac6 100644 --- a/code/ryzom/client/src/interface_v3/interface_parser.cpp +++ b/code/ryzom/client/src/interface_v3/interface_parser.cpp @@ -39,7 +39,7 @@ #include "view_bitmap.h" #include "view_bitmap_faber_mp.h" #include "view_bitmap_combo.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "view_text_formated.h" #include "view_text_id.h" #include "view_text_id_formated.h" diff --git a/code/ryzom/client/src/interface_v3/interface_pointer.h b/code/ryzom/client/src/interface_v3/interface_pointer.h index e0e193baa..62605d6e3 100644 --- a/code/ryzom/client/src/interface_v3/interface_pointer.h +++ b/code/ryzom/client/src/interface_v3/interface_pointer.h @@ -27,6 +27,7 @@ namespace NLGUI class CCtrlBase; class CCtrlBaseButton; class CInterfaceGroup; + class CViewText; } using namespace NLGUI; @@ -60,7 +61,7 @@ public: typedef CInterfacePtr::TInterfacePtr CInterfaceElementPtr; typedef CInterfacePtr::TInterfacePtr CInterfaceGroupPtr; typedef CInterfacePtr::TInterfacePtr CCtrlTextButtonPtr; -typedef CInterfacePtr::TInterfacePtr CViewTextPtr; +typedef CInterfacePtr::TInterfacePtr CViewTextPtr; typedef CInterfacePtr::TInterfacePtr CViewTextMenuPtr; typedef CInterfacePtr::TInterfacePtr CCtrlBasePtr; typedef CInterfacePtr::TInterfacePtr CCtrlBaseButtonPtr; diff --git a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp index e1e73deed..3f363258c 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp +++ b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp @@ -49,7 +49,7 @@ #include "action_handler_tools.h" #include "interface_manager.h" #include "nel/gui/interface_group.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "game_share/people_pd.h" #include "group_tree.h" #include "nel/gui/interface_link.h" diff --git a/code/ryzom/client/src/interface_v3/register_interface_elements.cpp b/code/ryzom/client/src/interface_v3/register_interface_elements.cpp index d9ac41023..299ff3f4b 100644 --- a/code/ryzom/client/src/interface_v3/register_interface_elements.cpp +++ b/code/ryzom/client/src/interface_v3/register_interface_elements.cpp @@ -20,7 +20,7 @@ #include "nel/gui/interface_element.h" #include "interface_3d_scene.h" #include "nel/gui/view_base.h" -#include "view_text.h" +#include "nel/gui/view_text.h" #include "view_text_id.h" #include "view_bitmap.h" #include "view_radar.h" diff --git a/code/ryzom/client/src/interface_v3/view_bitmap_faber_mp.h b/code/ryzom/client/src/interface_v3/view_bitmap_faber_mp.h index 839286c78..22c7b3e0b 100644 --- a/code/ryzom/client/src/interface_v3/view_bitmap_faber_mp.h +++ b/code/ryzom/client/src/interface_v3/view_bitmap_faber_mp.h @@ -24,7 +24,7 @@ ///\todo nico : do the real display when item icons are available -#include "view_text.h" +#include "nel/gui/view_text.h" /** * class used to display mps for faber interface diff --git a/code/ryzom/client/src/interface_v3/view_link.h b/code/ryzom/client/src/interface_v3/view_link.h index ba30fafd2..169487a1d 100644 --- a/code/ryzom/client/src/interface_v3/view_link.h +++ b/code/ryzom/client/src/interface_v3/view_link.h @@ -19,7 +19,7 @@ #ifndef NL_VIEW_LINK_H #define NL_VIEW_LINK_H -#include "view_text.h" +#include "nel/gui/view_text.h" /** * class implementing a link view diff --git a/code/ryzom/client/src/interface_v3/view_text.cpp b/code/ryzom/client/src/interface_v3/view_text.cpp deleted file mode 100644 index fc50c1b76..000000000 --- a/code/ryzom/client/src/interface_v3/view_text.cpp +++ /dev/null @@ -1,2597 +0,0 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/bit_mem_stream.h" -#include "nel/misc/i18n.h" - -#include "view_text.h" -#include "nel/gui/view_renderer.h" -#include "nel/gui/widget_manager.h" -#include "nel/gui/group_container_base.h" -#include "nel/gui/ctrl_tooltip.h" -#include "nel/misc/xml_auto_ptr.h" -#include "nel/gui/lua_ihm.h" -#include "nel/gui/view_pointer_base.h" - -using namespace std; -using namespace NLMISC; -using namespace NL3D; - -typedef std::string::size_type TCharPos; // index of a chracter in a string - -REGISTER_UI_CLASS(CViewText) - -// *************************************************************************** -void CViewText::setupDefault () -{ - _CaseMode = CaseNormal; - _Underlined = false; - _ContinuousUpdate = false; - _Active = true; - _X = 0; - _Y = 0; - _W = 0;; - _H = 0; - _SizeRef = 0; - _SizeDivW = 10; - _SizeDivH = 10; - _ParentPosRef = Hotspot_BL; - _PosRef = Hotspot_BL; - - _FontSize = 12 + - CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont ).getValSInt32(); - _Color = CRGBA(255,255,255,255); - _Shadow = false; - _ShadowColor = CRGBA(0,0,0,255); - - _MultiLine = false; - _TextMode = DontClipWord; - _MultiLineSpace = 8; - _LineMaxW = 16384; - _MultiLineMaxWOnly = false; - _MultiLineClipEndSpace = false; - _LastMultiLineMaxW = 0; - _MultiMaxLine = 0; - _Index = 0xFFFFFFFF; - - _FontWidth= 0; - _FontHeight = 0; - _FontLegHeight = 0; - - _TextSelection= false; - _TextSelectionStart= 0; - _TextSelectionEnd= std::numeric_limits::max(); - - _InvalidTextContext= true; - _FirstLineX = 0; - computeFontSize (); - - _SingleLineTextClamped= false; - _OverExtendViewText= false; - _OverExtendViewTextUseParentRect= false; - - _AutoClamp = false; - _ClampRight = true; // clamp on the right of the text - - _LetterColors = NULL; - _Setuped= false; - _AutoClampOffset = 0; -} - -// *************************************************************************** - -NLMISC_REGISTER_OBJECT(CViewBase, CViewText, std::string, "text"); - -CViewText::CViewText(const TCtorParam ¶m) -:CViewBase(param) -{ - setupDefault (); -} - -///constructor -// *************************************************************************** -CViewText:: CViewText (const std::string& id, const std::string Text, sint FontSize, - NLMISC::CRGBA Color, bool Shadow) - :CViewBase(TCtorParam()) -{ - _Id = id; - setupDefault (); - - _FontSize = FontSize + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); - _Color = Color; - _Shadow = Shadow; - setText(Text); - computeFontSize (); -} - -// *************************************************************************** -CViewText::~CViewText() -{ - if (_Index != 0xFFFFFFFF) - CViewRenderer::getTextContext()->erase (_Index); - clearLines(); - - if (!_Setuped) - for (uint i=0 ; i<_Tooltips.size() ; ++i) - delete _Tooltips[i]; - - _Tooltips.clear(); -} - -// *************************************************************************** -CViewText &CViewText::operator=(const CViewText &vt) -{ - if (_Index != 0xFFFFFFFF) - CViewRenderer::getTextContext()->erase (_Index); - - // Create database entries - _Active = vt._Active; - _X = vt._X; - _Y = vt._Y; - _W = vt._W; - _H = vt._H; - _SizeRef = vt._SizeRef; - _SizeDivW = vt._SizeDivW; - _SizeDivH = vt._SizeDivH; - _ParentPosRef = vt._ParentPosRef; - _PosRef = vt._PosRef; - - _FontSize = vt._FontSize; - _Color = vt._Color; - _Shadow = vt._Shadow; - _ShadowColor = vt._ShadowColor; - - _MultiLine = false; - _MultiLineSpace = 8; - _LineMaxW= 16384; - _MultiLineMaxWOnly = false; - _MultiLineClipEndSpace = false; - _LastMultiLineMaxW = 0; - _Index = 0xFFFFFFFF; - - _ModulateGlobalColor= vt._ModulateGlobalColor; - - - // remove previous lines - clearLines(); - _InvalidTextContext = true; - computeFontSize (); - - return *this; -} - -// *************************************************************************** -void CViewText::parseTextOptions (xmlNodePtr cur) -{ - CXMLAutoPtr prop; - - prop= (char*) xmlGetProp( cur, (xmlChar*)"color" ); - _Color = CRGBA(255,255,255,255); - if (prop) - _Color = convertColor(prop); - - prop= (char*) xmlGetProp (cur, (xmlChar*)"global_color"); - if(prop) - _ModulateGlobalColor= convertBool(prop); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"fontsize" ); - _FontSize = 12 + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); - if (prop) - { - fromString((const char*)prop, _FontSize); - _FontSize += CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); - } - - prop = (char*) xmlGetProp( cur, (xmlChar*)"shadow" ); - _Shadow = false; - if (prop) - _Shadow = convertBool(prop); - - prop= (char*) xmlGetProp( cur, (xmlChar*)"shadow_color" ); - _ShadowColor = CRGBA(0,0,0,255); - if (prop) - _ShadowColor = convertColor(prop); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"multi_line" ); - _MultiLine = false; - if (prop) - _MultiLine = convertBool(prop); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"justification" ); - if (prop) - { - if (nlstricmp("clip_word", (const char *) prop) == 0) _TextMode = ClipWord; - else if (nlstricmp("dont_clip_word", (const char *) prop) == 0) _TextMode = DontClipWord; - else if (nlstricmp("justified", (const char *) prop) == 0) _TextMode = Justified; - else nlwarning(" bad text mode"); - } - - prop = (char*) xmlGetProp( cur, (xmlChar*)"line_maxw" ); - _LineMaxW = 16384; - if (prop) - fromString((const char*)prop, _LineMaxW); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"multi_line_space" ); - _MultiLineSpace = 8; - if (prop) - fromString((const char*)prop, _MultiLineSpace); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"multi_line_maxw_only" ); - _MultiLineMaxWOnly = false; - if (prop) - _MultiLineMaxWOnly = convertBool(prop); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"multi_max_line" ); - _MultiMaxLine = 0; - if (prop) - fromString((const char*)prop, _MultiMaxLine); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"underlined" ); - _Underlined = false; - if (prop) - _Underlined = convertBool(prop); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"case_mode" ); - _CaseMode = CaseNormal; - if (prop) - { - sint32 caseMode; - fromString((const char*)prop, caseMode); - _CaseMode = (TCaseMode)caseMode; - } - - prop = (char*) xmlGetProp( cur, (xmlChar*)"over_extend_view_text" ); - _OverExtendViewText= false; - if(prop) - _OverExtendViewText= convertBool(prop); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"over_extend_parent_rect" ); - _OverExtendViewTextUseParentRect= false; - if(prop) - _OverExtendViewTextUseParentRect= convertBool(prop); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"auto_clamp" ); - _AutoClamp = false; - if (prop) - _AutoClamp = convertBool(prop); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"clamp_right" ); - _ClampRight = true; - if (prop) - _ClampRight = convertBool(prop); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"auto_clamp_offset" ); - _AutoClampOffset = 0; - if (prop) - fromString((const char*)prop, _AutoClampOffset); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"continuous_update" ); - if (prop) - { - _ContinuousUpdate = convertBool(prop); - } - - - computeFontSize (); -} - -/* -* parse an xml node and initialize the base view mambers. Must call CViewBase::parse -* \param cur : pointer to the xml node to be parsed -* \param parentGroup : the parent group of the view -* \partam id : a refence to the string that will receive the view ID -* \return true if success -*/ -// *************************************************************************** -bool CViewText::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup) -{ - -// const ucstring* tmp; - CXMLAutoPtr prop; - //try to get props that can be inherited from groups - //if a property is not defined, try to find it in the parent group. - //if it is undefined, set it to zero - - if (! CViewBase::parse(cur,parentGroup) ) - return false; - - //set w and h to 0 : they depend on the string contained - _W = 0; - _H = 0; - - //try to get the NEEDED specific props - parseTextOptions(cur); - - prop = (char*) xmlGetProp( cur, (xmlChar*)"hardtext" ); - if (prop) - { - const char *propPtr = prop; - _Text = ucstring(propPtr); - - if ((strlen(propPtr)>2) && (propPtr[0] == 'u') && (propPtr[1] == 'i')) - _Text = CI18N::get (propPtr); - setCase (_Text, _CaseMode); - } - - prop = (char*) xmlGetProp( cur, (xmlChar*)"hardtext_format" ); - if (prop) - { - const char *propPtr = prop; - if (_MultiLine) - { - setTextFormatTaged(CI18N::get(propPtr)); - } - else - { - setSingleLineTextFormatTaged(CI18N::get(propPtr)); - } - } - - invalidateContent (); - - return true; -} - -// *************************************************************************** -sint CViewText::getCurrentMultiLineMaxW() const -{ - if(_MultiLineMaxWOnly) - return _LineMaxW; - else - { - sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); - return std::min(parentWidth-(sint)(_XReal-_Parent->getXReal()), (sint)_LineMaxW); - } -} - - -// *************************************************************************** -void CViewText::checkCoords () -{ - if ((_MultiLine)&&(_Parent != NULL)) - { - // If never setuped, and if text is not empty - if (_Lines.size() == 0 && !_Text.empty()) - invalidateContent (); - - sint currentMaxW= getCurrentMultiLineMaxW(); - if ( _LastMultiLineMaxW != currentMaxW ) - { - if (_ContinuousUpdate) - { - _LastMultiLineMaxW = currentMaxW; - invalidateContent(); - } - else - { - CCtrlBase *pCB = CWidgetManager::getInstance()->getCapturePointerLeft(); - if (pCB != NULL) - { - if( pCB->isResizer() ) - { - // We are resizing !!!! - } - else - { - _LastMultiLineMaxW = currentMaxW; - invalidateContent(); - } - } - else - { - _LastMultiLineMaxW = currentMaxW; - invalidateContent(); - } - } - } - } - else - { - if (_Index == 0xFFFFFFFF) - invalidateContent (); - } -} -/* -* draw the view -*/ -// *************************************************************************** -void CViewText::draw () -{ - H_AUTO( RZ_Interface_CViewText_draw ) - - CViewRenderer &rVR = *CViewRenderer::getInstance(); - - // *** Out Of Clip? - sint32 ClipX, ClipY, ClipW, ClipH; - rVR.getClipWindow (ClipX, ClipY, ClipW, ClipH); - if (((_XReal) > (ClipX+ClipW)) || ((_XReal+_WReal) < ClipX) || - ((_YReal) > (ClipY+ClipH)) || ((_YReal+_HReal) < ClipY)) - return; - - // *** Screen Minimized? - uint32 w, h; - float oow, ooh; - rVR.getScreenSize (w, h); - if (rVR.isMinimized()) - return; - rVR.getScreenOOSize (oow, ooh); - - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - - - // *** get current color - CRGBA col, shcol; - if(getModulateGlobalColor()) - { - CRGBA gcfc = CWidgetManager::getInstance()->getGlobalColorForContent(); - col.modulateFromColor (_Color, gcfc); - shcol.modulateFromColor (_ShadowColor, gcfc); - } - else - { - col = _Color; - shcol = _ShadowColor; - col.A = (uint8)(((sint)col.A*((sint)CWidgetManager::getInstance()->getGlobalColorForContent().A+1))>>8); - shcol.A = (uint8)(((sint)shcol.A*((sint)CWidgetManager::getInstance()->getGlobalColorForContent().A+1))>>8); - } - - - // *** Draw multiline - if ((_MultiLine)&&(_Parent != NULL)) - { - if (_Lines.size() == 0) return; - - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - - TextContext->setHotSpot (UTextContext::BottomLeft); - TextContext->setShaded (_Shadow); - TextContext->setShadeColor (shcol); - TextContext->setFontSize (_FontSize); - - float y = (float)(_YReal) * ooh; // y is expressed in scree, coordinates [0..1] - //y += _LinesInfos[_LinesInfos.size()-1].StringLine / h; - - // Y is the base line of the string, so it must be grown up. - y += (float)_FontLegHeight * ooh; - - sint y_line = _YReal+_FontLegHeight-2; - - // special selection code - if(_TextSelection) - { - sint charIndex = 0; - for (sint i = 0; i<(sint)_Lines.size(); i++) - { - CLine &currLine = *_Lines[i]; - for(uint k = 0; k < currLine.getNumWords(); ++k) - { - CWord &currWord = currLine.getWord(k); - charIndex += currWord.NumSpaces; - sint cStart= max(charIndex, (sint)_TextSelectionStart); - sint cEnd= min(charIndex+(sint)currWord.Text.length(), (sint)_TextSelectionEnd); - - // range must be valid - if(cStartsetStringSelection(currWord.Index, 0, 0); - } - - // next word - charIndex+= (sint)currWord.Text.length(); - } - charIndex += currLine.getEndSpaces() + (currLine.getLF() ? 1 : 0); - } - } - - // draw - for (sint i = (sint)_Lines.size()-1; i >= 0; --i) - { - CLine &currLine = *_Lines[i]; - // current x position - float px = (float) (_XReal + ((i==0) ? (sint)_FirstLineX : 0)); - // draw each words of the line - for(uint k = 0; k < currLine.getNumWords(); ++k) - { - CWord &currWord = currLine.getWord(k); - - // Change the current color - if(currWord.Format.Color==CRGBA::White) - TextContext->setStringColor(currWord.Index, col); - else - { - CRGBA mCol; - mCol.modulateFromColor(col, currWord.Format.Color); - TextContext->setStringColor(currWord.Index, mCol); - } - - // skip spaces before current word - float firstSpace = currWord.NumSpaces * currLine.getSpaceWidth(); - sint line_width = 0; - if (_Underlined) - { - line_width = (sint)floorf(currLine.getWidthWithoutSpaces() + currLine.getSpaceWidth()); - line_width -= (sint)floorf(firstSpace); - } - px += firstSpace; - // skip tabulation before current word - if(currWord.Format.TabX) - px= max(px, (float)(_XReal + currWord.Format.TabX*_FontWidth)); - - // draw. We take floorf px to avoid filtering of letters that are not located on a pixel boundary - rVR.drawText (_RenderLayer, floorf(px) * oow, y, currWord.Index, (float)ClipX * oow, (float)ClipY * ooh, - (float)(ClipX+ClipW) * oow, (float)(ClipY+ClipH) * ooh, *TextContext); - - // Draw a line - if (_Underlined) - rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line, line_width, 1, 0, false, rVR.getBlankTextureId(), col); - - // skip word - px += currWord.Info.StringWidth; - } - // go one line up - y += (_FontHeight + _MultiLineSpace) * ooh; - y_line += _FontHeight+_MultiLineSpace; - } - - // reset selection - if(_TextSelection) - { - for (sint i = 0; i<(sint)_Lines.size(); i++) - { - CLine &currLine = *_Lines[i]; - for(uint k = 0; k < currLine.getNumWords(); ++k) - { - TextContext->resetStringSelection(currLine.getWord(k).Index); - } - } - } - } - // *** Single Line Version (currently no support for text justification) - else - { - nlassert(_Index != 0xFFFFFFFF); - - TextContext->setHotSpot (UTextContext::BottomLeft); - TextContext->setShaded (_Shadow); - TextContext->setShadeColor (shcol); - TextContext->setFontSize (_FontSize); - - - if(_LetterColors!=NULL && !TextContext->isSameLetterColors(_LetterColors, _Index)) - { - TextContext->setLetterColors(_LetterColors, _Index); - } - - - float x = (float)(_XReal) * oow; - float y = (float)(_YReal) * ooh; - - // Y is the base line of the string, so it must be grown up. - y += (float)_FontLegHeight * ooh; - - // special selection code - if(_TextSelection) - // select subset. Arg, must skip spaces because not inserted in VertexBuffer. - setStringSelectionSkipingSpace(_Index, _Text, _TextSelectionStart, _TextSelectionEnd); - - // Change the current color - TextContext->setStringColor(_Index, col); - - // draw - rVR.drawText (_RenderLayer, x, y, _Index, (float)ClipX * oow, (float)ClipY * ooh, - (float)(ClipX+ClipW) * oow, (float)(ClipY+ClipH) * ooh, *TextContext); - - // Draw a line - if (_Underlined) - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_FontLegHeight-2, _WReal, 1, 0, false, rVR.getBlankTextureId(), col); - - // reset selection - if(_TextSelection) - TextContext->resetStringSelection(_Index); - - // if single line clamped, may allow to draw an over - if(isSingleLineTextClamped() && _OverExtendViewText && CWidgetManager::getInstance()->getPointer()) - { - // but must check first if mouse is over - sint32 x = CWidgetManager::getInstance()->getPointer()->getX(); - sint32 y = CWidgetManager::getInstance()->getPointer()->getY(); - bool mouseIn; - // use parent clip or self clip? - if(_OverExtendViewTextUseParentRect) - mouseIn= _Parent && _Parent->isIn(x,y); - else - mouseIn= isIn(x,y); - // if the mouse cursor is in the clip area - if(mouseIn) - { - // check the window under the mouse is the root window - CInterfaceGroup *pIG = CWidgetManager::getInstance()->getWindowUnder(x,y); - CInterfaceElement *pParent = this; - bool bFound = false; - while (pParent != NULL) - { - if (pParent == pIG) - { - bFound = true; - break; - } - pParent = pParent->getParent(); - } - - // ok => let this view text be the extend over one - if(bFound) - { - // last check: the window must not be currently moved - CGroupContainerBase *gc= dynamic_cast(pIG); - if(!gc || !gc->isMoving()) - { - CRGBA col= CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionViewTextOverBackColor).getValColor(); - CWidgetManager::getInstance()->setOverExtendViewText(this, col); - } - } - } - } - } - -} - -// *************************************************************************** -void CViewText::onAddToGroup() -{ - // Add tooltips if not done - if(!_Setuped) - setup(); -} - -// *************************************************************************** -void CViewText::setTextMode(TTextMode mode) -{ - if (mode != _TextMode) - { - _TextMode = mode; - invalidateContent (); - } -} - -// *************************************************************************** -void CViewText::setText(const ucstring & text) -{ - // common case: no special format, no case mode => easy cache test - if (_FormatTags.empty() && _CaseMode==CaseNormal) - { - if (text != _Text) - { - _Text = text; - // no need to call "setCase (_Text, _CaseMode);" since CaseNormal: - invalidateContent (); - } - } - else - { - // if the view text had some format before, no choice, must recompute all - if(!_FormatTags.empty()) - { - _Text = text; - setCase (_Text, _CaseMode); - invalidateContent (); - } - // else test if after the case change the cache succeed - else - { - // compute the temp cased text - ucstring tempText= text; - setCase(tempText, _CaseMode); - if(tempText!=_Text) - { - _Text = tempText; - invalidateContent (); - } - } - } - - // clear format tags if any - _FormatTags.clear(); -} - -// *************************************************************************** -void CViewText::setFontSize (sint nFontSize) -{ - _FontSize = nFontSize + CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); - computeFontSize (); - invalidateContent(); -} - -// *************************************************************************** -sint CViewText::getFontSize() const -{ - return _FontSize - CWidgetManager::getInstance()->getSystemOption( CWidgetManager::OptionAddCoefFont).getValSInt32(); -} - -// *************************************************************************** -void CViewText::setColor(const NLMISC::CRGBA & color) -{ - _Color = color; -} - -// *************************************************************************** -void CViewText::setShadow (bool bShadow) -{ - _Shadow = bShadow; - computeFontSize (); - invalidateContent(); -} - -// *************************************************************************** -void CViewText::setShadowColor(const NLMISC::CRGBA & color) -{ - _ShadowColor = color; -} - -// *************************************************************************** -void CViewText::setLineMaxW (sint nMaxW, bool invalidate) -{ - if(_LineMaxW!=nMaxW) - { - _LineMaxW = nMaxW; - if (invalidate) - invalidateContent(); - } -} - -// *************************************************************************** -int CViewText::luaSetLineMaxW(CLuaState &ls) -{ - CLuaIHM::checkArgCount(ls, "setLineMaxW", 1); - sint32 value; - if(CLuaIHM::popSINT32(ls, value)) - { - setLineMaxW(value); - } - return 0; -} - -// *************************************************************************** -void CViewText::setMultiLine (bool bMultiLine) -{ - _MultiLine = bMultiLine; - invalidateContent(); -} - -// *************************************************************************** -void CViewText::setMultiLineSpace (sint nMultiLineSpace) -{ - _MultiLineSpace = nMultiLineSpace; - invalidateContent(); -} - -// *************************************************************************** -void CViewText::setMultiLineMaxWOnly (bool state) -{ - _MultiLineMaxWOnly = state; - invalidateContent(); -} - -// *************************************************************************** -void CViewText::setMultiLineClipEndSpace (bool state) -{ - _MultiLineClipEndSpace= state; - invalidateContent(); -} - -// *************************************************************************** -uint CViewText::getFontWidth() const -{ - return _FontWidth; -} - -// *************************************************************************** -uint CViewText::getFontHeight() const -{ - return _FontHeight; -} - -// *************************************************************************** -uint CViewText::getFontLegHeight() const -{ - return _FontLegHeight; -} - -// *************************************************************************** -void CViewText::flushWordInLine(ucstring &ucCurrentWord, bool &linePushed, const CFormatInfo &wordFormat) -{ - // create a new line? - if(!linePushed) - { - _Lines.push_back(TLineSPtr(new CLine)); - linePushed= true; - } - // Append to the last line - _Lines.back()->addWord(ucCurrentWord, 0, wordFormat, _FontWidth); - // reset the word - ucCurrentWord = ucstring(""); -} - - -// *************************************************************************** -void CViewText::updateTextContextMultiLine(uint nMaxWidth) -{ - ucchar ucLetter; - UTextContext::CStringInfo si; - uint i; - // word state - ucstring ucCurrentWord; - CFormatInfo wordFormat; - // line state - float rWidthCurrentLine = 0, rWidthLetter; - bool linePushed= false; - // for all the text - uint textSize= (uint)_Text.size(); - uint formatTagIndex= 0; - for (i = 0; i < textSize; ++i) - { - if(isFormatTagChange(i, formatTagIndex)) - { - // If the word was not empty before this color tag - if(!ucCurrentWord.empty()) - flushWordInLine(ucCurrentWord, linePushed, wordFormat); - - // get new color and skip ctIndex. - getFormatTagChange(i, formatTagIndex, wordFormat); - - // Ensure the line witdh count the tab - rWidthCurrentLine= max(rWidthCurrentLine, (float)wordFormat.TabX*_FontWidth); - } - - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - - // Parse the letter - { - ucLetter = _Text[i]; - if (ucLetter == ucchar('\n')) - { - flushWordInLine(ucCurrentWord, linePushed, wordFormat); - // reset line state - linePushed= false; - rWidthCurrentLine = 0; - } - else - { - ucstring ucStrLetter; - ucStrLetter= ucLetter; - si = TextContext->getStringInfo (ucStrLetter); - rWidthLetter = (si.StringWidth); - if ((rWidthCurrentLine + rWidthLetter) > nMaxWidth) - { - flushWordInLine(ucCurrentWord, linePushed, wordFormat); - - // reset line state, and begin with the cut letter - linePushed= false; - rWidthCurrentLine = rWidthLetter; - ucCurrentWord = ucLetter; - } - else - { - // Grow the current word - ucCurrentWord += ucLetter; - rWidthCurrentLine += rWidthLetter; - } - } - } - } - if (ucCurrentWord.length()) - { - flushWordInLine(ucCurrentWord, linePushed, wordFormat); - } -} - - -// *************************************************************************** -void CViewText::addDontClipWordLine(std::vector &currLine) -{ - // create a new line - _Lines.push_back(TLineSPtr(new CLine)); - - // Fill it with words. if all words of same color, create only one CWord - if (!currLine.empty()) - { - CFormatInfo lineWordFormat= currLine[0].Format; - ucstring lineWord; - for(uint i=0;iaddWord(lineWord, 0, lineWordFormat, _FontWidth); - // get new lineWordFormat - lineWordFormat= currLine[i].Format; - // and clear - lineWord.clear(); - } - - // Append the word with space to the lineWord. - ucstring blank; - blank.resize(currLine[i].NumSpaces, (ucchar) ' '); - lineWord += blank; - lineWord += currLine[i].Text; - } - - if(!lineWord.empty()) - _Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth); - - // clear - currLine.clear(); - } -} - -// *************************************************************************** -void CViewText::updateTextContextMultiLineJustified(uint nMaxWidth, bool expandSpaces) -{ - UTextContext::CStringInfo si; - // - TCharPos currPos = 0; - // - static const ucstring spaceStr(" "); - // precLineWidth valid only id precedent line is part of same paragraph. - float precLineWidth= 0; - float lineWidth = (float)_FirstLineX; // width of the current line - uint numWordsInLine = 0; // number of words in the current line - bool isParagraphStart = true; // A paragraph is a group of characters between 2 \n - bool lineFeed; - bool breakLine; - // - vector currLine; // if spaces are not expanded, all words of a line are inserted here (NB: index and stringInfo not filled) - ucstring wordValue; - CFormatInfo wordFormat; - uint formatTagIndex= 0; - // - while (currPos != _Text.length()) - { - TCharPos spaceEnd; - TCharPos wordEnd; - uint numSpaces; - float newLineWidth; - breakLine = false; - // - if (_Text[currPos] == (ucchar) '\n') - { - lineFeed = true; - } - else - { - lineFeed = false; - // Skip spaces and count them - spaceEnd = _Text.find_first_not_of(spaceStr, currPos); - if (spaceEnd == std::string::npos) - { - spaceEnd = _Text.length(); - } - numSpaces = (uint) (spaceEnd - currPos); - if (!isParagraphStart && numSpaces != 0 && numWordsInLine == 0) // Are these the first spaces of the line ? - { - if (!_Lines.empty()) - { - /* Yoyo: I changed this (added the "cut space"), because in editBox, it is so strange when - the word hit the end of line, and if you add spaces just after, nothing happens because - cursor pos is clamped at end of line. - */ - // Cannot put all of thoses spaces to the prec end of line? - if(_MultiLineClipEndSpace && precLineWidth + numSpaces * _SpaceWidth > nMaxWidth) - { - // put some of these spaces at the end of the previous line. - sint maxNumSpaces= (sint)floorf((nMaxWidth - precLineWidth) / _SpaceWidth); - _Lines.back()->setEndSpaces(maxNumSpaces); - // And start the new lines with the remaining spaces. - numSpaces-= maxNumSpaces; - currPos+= maxNumSpaces; - } - else - { - // ok, put all spaces to previous line - _Lines.back()->setEndSpaces(numSpaces); - currPos = spaceEnd; - numSpaces= 0; - } - if(currPos >=_Text.length()) - break; - } - } - - // Detect change of wordFormat at the begining of the word - if(isFormatTagChange((uint)spaceEnd, formatTagIndex)) - { - getFormatTagChange((uint)spaceEnd, formatTagIndex, wordFormat); - } - - // Get word until a space, a \n, or a FormatTagChange is encountered - uint i; - for(i= (uint)spaceEnd;i<(uint)_Text.length();i++) - { - ucchar c= _Text[i]; - if(c==' ' || c=='\n') - break; - // If change of color tag, stop the word, but don't take the new color now. - if(isFormatTagChange(i, formatTagIndex)) - break; - } - wordEnd = i; - - - // Get the word value. - wordValue = _Text.substr(spaceEnd, wordEnd - spaceEnd); - // compute width of word - si = CViewRenderer::getTextContext()->getStringInfo(wordValue); - - // compute size of spaces/Tab + word - newLineWidth = lineWidth + numSpaces * _SpaceWidth; - newLineWidth = max(newLineWidth, (float)wordFormat.TabX*_FontWidth); - newLineWidth+= si.StringWidth; - } - // - // Does the word go beyond the end of line ? - if (!lineFeed && newLineWidth > (float) nMaxWidth) - { - // Have we enough room for this word on a line ? - bool roomForThisWord = (numWordsInLine > 0) || ( (newLineWidth - lineWidth) < (float) nMaxWidth ); - - // not enough room for that word - // If it is the only word of the line, just split it - // Otherwise, scale the spaces between words so that the line as the maximum width - if (roomForThisWord) - { - if (expandSpaces) - { - nlassert(_Lines.size() > 0); - nlassert(_Lines.back()->getNumWords() > 0); - - // Yoyo: if the line has tab, then don't justify - if(wordFormat.TabX > 0) - _Lines.back()->setSpaceWidth(_SpaceWidth); - else - { - // Scale the width so that the line has the maximum width - float roomForSpaces = nMaxWidth - _Lines.back()->getWidthWithoutSpaces(); - uint startNumSpaces = _Lines.back()->getNumSpaces(); - if (startNumSpaces != 0) - { - _Lines.back()->setSpaceWidth(roomForSpaces / startNumSpaces); - } - else - { - _Lines.back()->setSpaceWidth(_SpaceWidth); - } - } - } - else - { - breakLine = true; - } - // we dont change the position in the input string so that the current will be processed on the next line - - } - else // it is the only word on the line.. - { - // .. so split it - // 1) Check if spaces go beyond the end of line - if (numSpaces * _SpaceWidth > nMaxWidth) - { - uint maxNumSpaces = std::max(1U, (uint) (nMaxWidth / _SpaceWidth)); - CWord spaceWord; // a word with only spaces in it - spaceWord.build (ucstring (""), maxNumSpaces); - spaceWord.Format= wordFormat; - _Lines.push_back(TLineSPtr(new CLine)); - _Lines.back()->addWord(spaceWord, _FontWidth); - if (expandSpaces) - { - _Lines.back()->setSpaceWidth(nMaxWidth / (float) maxNumSpaces); - } - else - { - _Lines.back()->setSpaceWidth(_SpaceWidth); - } - currPos = currPos + maxNumSpaces; - } - else - { - float px = numSpaces * _SpaceWidth; - uint currChar = 0; - ucstring oneChar(" "); - for(currChar = 0; currChar < wordValue.length(); ++currChar) - { - oneChar = wordValue[currChar]; - si = CViewRenderer::getTextContext()->getStringInfo(oneChar); - if ((uint) (px + si.StringWidth) > nMaxWidth) break; - px += si.StringWidth; - } - currChar = std::max((uint) 1, currChar); // must fit at least one character otherwise there's an infinite loop - wordValue = _Text.substr(spaceEnd, currChar); - CWord word; - word.build(wordValue, numSpaces); - word.Format= wordFormat; - _Lines.push_back(TLineSPtr(new CLine)); - float roomForSpaces = (float) nMaxWidth - word.Info.StringWidth; - if (expandSpaces && numSpaces != 0) - { - _Lines.back()->setSpaceWidth(roomForSpaces / (float) numSpaces); - } - else - { - _Lines.back()->setSpaceWidth(0); - } - _Lines.back()->addWord(word, _FontWidth); - currPos = currPos + numSpaces + currChar; - } - } - // reset line - numWordsInLine = 0; - precLineWidth= lineWidth; - lineWidth = 0; - isParagraphStart = false; - } - else if (!lineFeed) // the end of line hasn't been reached - { - if (expandSpaces) - { - // add in the current line (and create one if necessary) - if (numWordsInLine == 0) - { - _Lines.push_back(TLineSPtr(new CLine)); - _Lines.back()->setSpaceWidth(_SpaceWidth); - } - if (!wordValue.empty() || numSpaces != 0) - { - CWord word; - word.build(wordValue, numSpaces); - word.Format= wordFormat; - // update line width - _Lines.back()->addWord(word, _FontWidth); - ++numWordsInLine; - } - } - else - { - CWord word; - // Don't build here, this is used as temp data. - word.Text= wordValue; - word.NumSpaces= numSpaces; - word.Format= wordFormat; - // Append to the temp Data. - currLine.push_back(word); - - ++numWordsInLine; - } - lineWidth = newLineWidth; - currPos = wordEnd; - } - else - { - // '\n' was encountered - ++ currPos; - isParagraphStart = true; - } - if (lineFeed || breakLine) // '\n' was encoutered, or a linefeed has been asked - { - // !expandSpaces => insert minimum words according to word color. - if (!expandSpaces) - { - // Add the new line. - addDontClipWordLine(currLine); - // LineFeed? - if (lineFeed) - { - _Lines.back()->setLF(true); - } - } - // expandSpaces => just add a empty line. - else - { - if (numWordsInLine == 0) - { - // if nothing has been inserted in this line, create at least an empty line - _Lines.push_back(TLineSPtr(new CLine)); - } - if (lineFeed) - { - _Lines.back()->setLF(true); - } - } - lineWidth = 0.f; - numWordsInLine = 0; - } - } - - // if current line hasn't been pushed, add it - if (!expandSpaces && !currLine.empty()) - { - // Add new line - addDontClipWordLine(currLine); - } - - // if the text ends with \n, must insert the last line ourself - if (!_Text.empty() && _Text[_Text.length() - 1] == (ucchar) '\n') - { - _Lines.push_back(TLineSPtr(new CLine)); - } -} - - -// *************************************************************************** -void CViewText::updateTextContext () -{ - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - - TextContext->setHotSpot (UTextContext::BottomLeft); - TextContext->setShaded (_Shadow); - TextContext->setFontSize (_FontSize); - - // default state - _SingleLineTextClamped= false; - - if ((_MultiLine)&&(_Parent != NULL)) - { - sint nMaxWidth = getCurrentMultiLineMaxW(); - _LastMultiLineMaxW = nMaxWidth; - clearLines(); - if (nMaxWidth <= 0) - { - // parent size may not be known yet - return; - } - switch(_TextMode) - { - case ClipWord: updateTextContextMultiLine(nMaxWidth); break; - case DontClipWord: updateTextContextMultiLineJustified(nMaxWidth, false); break; - case Justified: updateTextContextMultiLineJustified(nMaxWidth, true); break; - } - - // Special case for multiline limited in number of lines - if ((_Lines.size() > 0) && (_MultiMaxLine > 0) && (_Lines.size() > _MultiMaxLine)) - { - while (_Lines.size() > _MultiMaxLine) - { - _Lines.back()->clear(); - _Lines.pop_back(); - } - _Lines.pop_back(); - CViewText::CLine *endLine = new CViewText::CLine; - CViewText::CWord w; - w.build(string("...")); - endLine->addWord(w, _FontWidth); - _Lines.push_back(TLineSPtr(endLine)); - } - - // Calculate size - float rTotalW = 0; - for (uint i = 0; i < _Lines.size(); ++i) - { - rTotalW = std::max(_Lines[i]->getWidth() + ((i==0)?_FirstLineX:0), rTotalW); - } - _W = (sint)rTotalW; - _H = std::max(_FontHeight, uint(_FontHeight * _Lines.size() + std::max(0, sint(_Lines.size()) - 1) * _MultiLineSpace)); - - // Compute tooltips size - if (_Tooltips.size() > 0) - for (uint i=0 ; i<_Lines.size() ; ++i) - { - for (uint j=0 ; j<_Lines[i]->getNumWords() ; ++j) - { - CWord word = _Lines[i]->getWord(j); -// float w = _Lines[i]->getWidth(); - - if (word.Format.IndexTt != -1) - { - if (_Tooltips.size() > (uint)word.Format.IndexTt) - { - CCtrlToolTip *pTooltip = _Tooltips[word.Format.IndexTt]; - - sint y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - i - 1)); - - pTooltip->setX(0); - pTooltip->setY(y); - pTooltip->setW(getCurrentMultiLineMaxW()); - pTooltip->setH(_FontHeight); - } - } - } - } - } - else // Single line code - { - if (_Index != 0xFFFFFFFF) - TextContext->erase (_Index); - - // Common case: no W clamp - _Index = TextContext->textPush (_Text); - _Info = TextContext->getStringInfo (_Index); - _W = (sint)(_Info.StringWidth); - - // Rare case: clamp W => recompute slowly, cut letters - if(_W>_LineMaxW) - { - TextContext->erase (_Index); - - ucchar ucLetter; - UTextContext::CStringInfo si; - ucstring ucCurrentLine; - ucCurrentLine.reserve(_Text.size()); - // Append ... to the end of line - si = TextContext->getStringInfo (ucstring("...")); - float dotWidth= si.StringWidth; - float rWidthCurrentLine = 0, rWidthLetter; - // for all the text - if (_ClampRight) - { - for (uint i = 0; i < _Text.size(); ++i) - { - ucLetter= _Text[i]; - ucstring ucStrLetter; - ucStrLetter= ucLetter; - si = TextContext->getStringInfo (ucStrLetter); - rWidthLetter = (si.StringWidth); - if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW) - { - break; - } - else - { - // Grow the current line - ucCurrentLine += ucLetter; - rWidthCurrentLine += rWidthLetter; - } - } - - // Add the dots - ucCurrentLine+= "..."; - } - else - { - for (sint i = (sint)_Text.size() - 1; i >= 0; --i) - { - ucLetter= _Text[i]; - ucstring ucStrLetter; - ucStrLetter= ucLetter; - si = TextContext->getStringInfo (ucStrLetter); - rWidthLetter = (si.StringWidth); - if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW) - { - break; - } - else - { - // Grow the current line - ucCurrentLine = ucLetter + ucCurrentLine; - rWidthCurrentLine += rWidthLetter; - } - } - - // Add the dots - ucCurrentLine = "..." + ucCurrentLine; - } - - // And so setup this trunc text - _Index = TextContext->textPush (ucCurrentLine); - _Info = TextContext->getStringInfo (_Index); - _W = (sint)(_Info.StringWidth); - - _SingleLineTextClamped= true; - } - - // same height always - _H = _FontHeight; - } - - _InvalidTextContext= false; -} - -// *************************************************************************** -void CViewText::updateCoords() -{ - if (_AutoClamp) - { - CViewBase::updateCoords (); - if (_Parent) - { - CInterfaceGroup *parent = _Parent; - // avoid resizing parents to compute the limiter - while (parent && (parent->getResizeFromChildW() || parent->isGroupList() )) - { - // NB nico : the dynamic_cast for CGroupList is bad!! - // can't avoid it for now, because, CGroupList implicitly does a "resize from child" in its update coords - // ... - parent = parent->getParent(); - } - if (parent) - { - if (_ClampRight) - { - sint32 parentRight = parent->getXReal() + parent->getWReal() - (sint32) _AutoClampOffset; - setLineMaxW(std::max((sint32) 0, parentRight - _XReal)); - } - else - { - sint32 parentLeft = parent->getXReal() + (sint32) _AutoClampOffset; - setLineMaxW(std::max((sint32) 0, _XReal + _WReal - parentLeft)); - } - } - } - } - - if(_InvalidTextContext) - updateTextContext(); - - CViewBase::updateCoords (); -} - -// *************************************************************************** -sint CViewText::getLineFromIndex(uint index, bool cursorDisplayedAtEndOfPreviousLine /* = true*/) const -{ - if (index > _Text.length()) return -1; - if (_MultiLine) - { - uint charIndex = 0; - for(sint i = 0; i < (sint) _Lines.size(); ++i) - { - CLine &currLine = *_Lines[i]; - uint newCharIndex = charIndex + currLine.getNumChars() + currLine.getEndSpaces() + (currLine.getLF() ? 1 : 0); - if (newCharIndex > index) - { - if (i != 0 && cursorDisplayedAtEndOfPreviousLine && charIndex == index) - { - return i - 1; - } - else - { - return i; - } - } - charIndex = newCharIndex; - } - return (sint)_Lines.size() - 1; - } - else - { - return 0; - } -} - -// *************************************************************************** -sint CViewText::getLineStartIndex(uint line) const -{ - uint charIndex = 0; - if (line >= _Lines.size()) return -1; - for(uint i = 0; i < line; ++i) - { - CLine &currLine = *_Lines[i]; - charIndex += currLine.getNumChars() + currLine.getEndSpaces() + (currLine.getLF() ? 1 : 0); - } - // skip all spaces at start of line (unless there are only spaces in the line) - std::string::size_type nextPos = _Text.find_first_not_of((ucchar) ' ', charIndex); - if (nextPos != std::string::npos) - { - if (getLineFromIndex(charIndex) == (sint) line) - { - return (sint) nextPos; - } - } - return charIndex; -} - -// *************************************************************************** -void CViewText::getLineEndIndex(uint line, sint &index, bool &endOfPreviousLine) const -{ - sint startIndex = getLineStartIndex(line); - if (startIndex == -1) - { - index = -1; - endOfPreviousLine = false; - return; - } - index = startIndex + _Lines[line]->getNumChars() + _Lines[line]->getEndSpaces(); - endOfPreviousLine = !_Lines[line]->getLF(); -} - -// *************************************************************************** -void CViewText::setHardText (const std::string &ht) -{ -// ucstring Text = ucstring(ht); - ucstring Text; - if ((ht.size()>2) && (ht[0] == 'u') && (ht[1] == 'i')) - Text = CI18N::get (ht); - else - Text.fromUtf8(ht); - setText(Text); -} - -// *************************************************************************** -string CViewText::getColorAsString() const -{ - return NLMISC::toString(_Color.R) + " " + NLMISC::toString(_Color.G) + " " + NLMISC::toString(_Color.B) + " " + NLMISC::toString(_Color.A); -} - -// *************************************************************************** -void CViewText::setColorAsString(const string &ht) -{ - _Color = convertColor (ht.c_str()); -} - -// *************************************************************************** -NLMISC::CRGBA CViewText::getColorRGBA() const -{ - return _Color; -} - -// *************************************************************************** -void CViewText::setColorRGBA(NLMISC::CRGBA col) -{ - _Color = col; -} - -// *************************************************************************** -void CViewText::getCharacterPositionFromIndex(sint index, bool cursorAtPreviousLineEnd, sint &x, sint &y, sint &height) const -{ - NLMISC::clamp(index, 0, (sint) _Text.length()); - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - TextContext->setHotSpot (UTextContext::BottomLeft); - TextContext->setShaded (_Shadow); - TextContext->setFontSize (_FontSize); -// CViewRenderer &rVR = *CViewRenderer::getInstance(); - height = getFontHeight(); - // - if (_MultiLine) - { - uint charIndex = 0; - // special case for end of text - if (index == (sint) _Text.length()) - { - y = 0; - if (_Lines.empty()) - { - x = 0; - } - else - { - CLine &lastLine = *_Lines.back(); - x = (sint) (lastLine.getWidth() + lastLine.getEndSpaces() * lastLine.getSpaceWidth()); - sint nMaxWidth = getCurrentMultiLineMaxW(); - x = std::min(x, nMaxWidth); - } - return; - } - for(sint i = 0; i < (sint) _Lines.size(); ++i) - { - if (i != 0 && charIndex == (uint) index && cursorAtPreviousLineEnd) - { - // should display the character at the end of previous line - CLine &currLine = *_Lines[i - 1]; - y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - i)); - x = (sint) (currLine.getWidth() + currLine.getEndSpaces() * currLine.getSpaceWidth()); - sint nMaxWidth = getCurrentMultiLineMaxW(); - x = std::min(x, nMaxWidth); - return; - } - CLine &currLine = *_Lines[i]; - uint newCharIndex = charIndex + currLine.getNumChars() + currLine.getEndSpaces() + (_Lines[i]->getLF() ? 1 : 0); - if ((sint) newCharIndex > index) - { - // ok, this line contains the character, now, see which word contains it. - y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - 1 - i)); - // see if the index is in the spaces at the end of line - if (index - charIndex >= currLine.getNumChars()) - { - uint numSpaces = index - charIndex - currLine.getNumChars(); - x = (sint) (currLine.getWidth() + numSpaces * _SpaceWidth); - sint nMaxWidth = getCurrentMultiLineMaxW(); - x = std::min(x, nMaxWidth); - return; - } - // now, search containing word in current line - float px = (float)_FirstLineX; - for(uint k = 0; k < currLine.getNumWords(); ++k) - { - CWord &currWord = currLine.getWord(k); - if ((sint) (charIndex + currWord.NumSpaces + currWord.Text.length()) >= index) - { - // character is in currWord or the in spaces preceding it - // check if the character is in the word - if ((uint) (index - charIndex) > currWord.NumSpaces) - { - // get the x position - ucstring subStr = currWord.Text.substr(0, index - charIndex - currWord.NumSpaces); - // compute the size - UTextContext::CStringInfo si = TextContext->getStringInfo(subStr); - x = (sint) (px + si.StringWidth + currWord.NumSpaces * currLine.getSpaceWidth()); - height = getFontHeight(); - return; - } - else - { - // character is in the spaces preceding the word - x = (sint) (px + currLine.getSpaceWidth() * (index - charIndex)); - height = getFontHeight(); - return; - } - } - charIndex += (uint)currWord.Text.length() + currWord.NumSpaces; - px += currWord.NumSpaces * currLine.getSpaceWidth() + currWord.Info.StringWidth; - } - } - charIndex = newCharIndex; - } - - } - else - { - // get the x position - ucstring subStr = _Text.substr(0, index); - // compute the size - UTextContext::CStringInfo si = TextContext->getStringInfo(subStr); - y = 0; - x = (sint) si.StringWidth; - } -} - -// *************************************************************************** -// Tool fct : From a word and a x coordinate, give the matching character index -static uint getCharacterIndex(const ucstring &textValue, float x) -{ - float px = 0.f; - UTextContext::CStringInfo si; - ucstring singleChar(" "); - uint i; - for (i = 0; i < textValue.length(); ++i) - { - // get character width - singleChar[0] = textValue[i]; - si = CViewRenderer::getTextContext()->getStringInfo(singleChar); - px += si.StringWidth; - // the character is at the i - 1 position - if (px > x) - { - // if the half of the character is after the cursor, then prefer select the next one (like in Word) - if(px-si.StringWidth/2 < x) - i++; - break; - } - } - return i; -} - -// *************************************************************************** -void CViewText::getCharacterIndexFromPosition(sint x, sint y, uint &index, bool &cursorAtPreviousLineEnd) const -{ - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - - // setup the text context - TextContext->setHotSpot (UTextContext::BottomLeft); - TextContext->setShaded (_Shadow); - TextContext->setFontSize (_FontSize); - // find the line where the character is -// CViewRenderer &rVR = *CViewRenderer::getInstance(); - uint charPos = 0; - if (_MultiLine) - { - // seek the line - float py = 0.f; - if (py > y) - { - index = (uint)_Text.length(); - cursorAtPreviousLineEnd = false; - return; - } - sint line; - for (line = (uint)_Lines.size() - 1; line >= 0; --line) - { - float newPy = py + _FontHeight + _MultiLineSpace; - if (newPy > y) - { - break; - } - py = newPy; - } - if (line == -1) - { - index = 0; - cursorAtPreviousLineEnd = false; - return; // above the first line, so take character 0 - } - // compute character index at start of line - sint i; - for (i = 0; i < line; ++i) - { - charPos += _Lines[i]->getNumChars() + _Lines[i]->getEndSpaces() + (_Lines[i]->getLF() ? 1 : 0); - } - // seek word that contains the character - CLine &currLine = *_Lines[line]; - // See if character is in the ending spaces - if (x >= (sint) currLine.getWidth()) - { - // Add _SpaceWidth/2 to select between chars - sint numSpaces = _SpaceWidth != 0 ? (sint) (((float) x + _SpaceWidth/2 - currLine.getWidth()) / _SpaceWidth) - : 0; - clamp(numSpaces, 0, (sint)currLine.getEndSpaces()); - index = charPos + currLine.getNumChars() + numSpaces; - cursorAtPreviousLineEnd = !_Lines[i]->getLF(); - return; - } - - float px = (float)_FirstLineX; - for(uint k = 0; k < currLine.getNumWords(); ++k) - { - CWord &currWord = currLine.getWord(k); - float spacesWidth = currLine.getSpaceWidth() * currWord.NumSpaces; - float newPx = px + currWord.Info.StringWidth + spacesWidth; - if (newPx >= x) // if the word contains the x position.. - { - if (x < (px + spacesWidth)) - { - // the coords x is in the spaces that are preceding the word - // Add spaceWidth/2 to select between chars - sint numSpaces = currLine.getSpaceWidth() != 0 ? (sint) ((x + currLine.getSpaceWidth()/2 - px) / currLine.getSpaceWidth()) - : 0; - clamp(numSpaces, 0, (sint)currWord.NumSpaces); - index = numSpaces + charPos; - cursorAtPreviousLineEnd = false; - return; - } - else - { - // the coord is in the word itself - index = charPos + currWord.NumSpaces + getCharacterIndex(currWord.Text, (float) x - (px + spacesWidth)); - cursorAtPreviousLineEnd = false; - return; - } - } - px = newPx; - charPos += (uint)currWord.Text.length() + currWord.NumSpaces; - } - index = charPos; - cursorAtPreviousLineEnd = false; - return; - } - else - { - cursorAtPreviousLineEnd = false; - if (y < 0) - { - index = (uint)_Text.length(); - return; - } - if (y > (sint) _FontHeight) - { - index = 0; - return; - } - index = getCharacterIndex(_Text, (float) x); - return; - } -} - -// *************************************************************************** -void CViewText::enableStringSelection(uint start, uint end) -{ - _TextSelection= true; - _TextSelectionStart= start; - _TextSelectionEnd= end; -} - -// *************************************************************************** -void CViewText::disableStringSelection() -{ - _TextSelection= false; - _TextSelectionStart= 0; - _TextSelectionEnd= std::numeric_limits::max(); -} - -// *************************************************************************** -void CViewText::setStringSelectionSkipingSpace(uint stringId, const ucstring &text, sint charStart, sint charEnd) -{ - sint quadStart= charStart; - sint quadSize= charEnd-charStart; - sint j; - for(j=0;jsetStringSelection(stringId, quadStart, quadSize); -} - -// *************************************************************************** -void CViewText::clearLines() -{ - for(uint k = 0; k < _Lines.size(); ++k) - { - _Lines[k]->clear(); - } - _Lines.clear(); -} - -// *************************************************************************** -uint CViewText::getNumLine() const -{ - if (_MultiLine) - { - return (uint)_Lines.size(); - } - else - { - return _Text.empty() ? 0 : 1; - } -} - -// *************************************************************************** -uint CViewText::getFirstLineX() const -{ - return _FirstLineX; -} - -// *************************************************************************** -uint CViewText::getLastLineW () const -{ - if (!_Lines.empty()) - return (uint)_Lines.back()->getWidth(); - return 0; -} - -// *************************************************************************** -void CViewText::setFirstLineX(uint firstLineX) -{ - _FirstLineX = firstLineX; -} - -///////////////////////////////////// -// CViewText::CLine implementation // -///////////////////////////////////// - -// *************************************************************************** -CViewText::CLine::CLine() : _NumChars(0), - _NumSpaces(0), - _SpaceWidth(0.f), - _StringLine(0), - _WidthWithoutSpaces(0.f), - _EndSpaces(0), - _HasLF(false) -{ -} - -// *************************************************************************** -void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, uint fontWidth) -{ - CWord word; - word.build(text, numSpaces); - word.Format= wordFormat; - addWord(word, fontWidth); -} - -// *************************************************************************** -void CViewText::CLine::addWord(const CWord &word, uint fontWidth) -{ - _Words.push_back(word); - _NumChars += word.NumSpaces + uint(word.Text.length()); - _NumSpaces += word.NumSpaces; - if (fabsf(word.Info.StringLine) > fabsf(_StringLine)) - { - _StringLine = word.Info.StringLine; - } - // the width of the line must reach at least the Tab - _WidthWithoutSpaces= max(_WidthWithoutSpaces, word.Format.TabX * float(fontWidth)); - // append the text space - _WidthWithoutSpaces += word.Info.StringWidth; -} - -// *************************************************************************** -void CViewText::CLine::clear() -{ - for(uint k = 0; k < _Words.size(); ++k) - { - if (_Words[k].Index != 0xffffffff) - CViewRenderer::getTextContext()->erase(_Words[k].Index); - } - _Words.clear(); - _NumChars = 0; - _SpaceWidth = 0.f; -} - -// *************************************************************************** -void CViewText::CLine::resetTextIndex() -{ - for(uint k = 0; k < _Words.size(); ++k) - { - _Words[k].Index = 0xffffffff; - } -} - -// *************************************************************************** -void CViewText::CWord::build(const ucstring &text, uint numSpaces/*=0*/) -{ - Text = text; - NumSpaces = numSpaces; - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - Index = TextContext->textPush(text); - Info = TextContext->getStringInfo(Index); -} - -// *************************************************************************** -void CViewText::removeEndSpaces() -{ - sint i = (sint)_Text.size()-1; - while ((i>=0) && ((_Text[i] < 0x20) || (_Text[i] == ' '))) - { - i--; - } - _Text.resize (i+1); -} - -// *************************************************************************** -sint32 CViewText::getMaxUsedW() const -{ - static const ucstring spaceStr(" \t"); - static const ucstring lineFeedStr("\n"); - float maxWidth = 0; - - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - TextContext->setHotSpot (UTextContext::BottomLeft); - TextContext->setShaded (_Shadow); - TextContext->setFontSize (_FontSize); - - TCharPos linePos = 0; - while (linePos < _Text.length()) - { - // Get the end of the line - float lineWidth = 0; - TCharPos lineEnd; - lineEnd = _Text.find_first_of(lineFeedStr, linePos); - if (lineEnd == std::string::npos) - { - lineEnd = _Text.length(); - } - - ucstring lineValue; - lineValue = _Text.substr(linePos, lineEnd - linePos); - - TCharPos currPos = 0; - while (currPos != lineValue.length()) - { - TCharPos spaceEnd; - TCharPos wordEnd; - uint numSpaces; - - // Skip spaces and count them - spaceEnd = lineValue.find_first_not_of(spaceStr, currPos); - if (spaceEnd == std::string::npos) - { - spaceEnd = lineValue.length(); - } - numSpaces = (uint) (spaceEnd - currPos); - - // Get word until a space or a \n is encountered - wordEnd = lineValue.find_first_of(spaceStr, spaceEnd); - if (wordEnd == std::string::npos) - { - wordEnd = lineValue.length(); - } - - ucstring wordValue; - wordValue = lineValue.substr(spaceEnd, wordEnd - spaceEnd); - - // compute width of word - UTextContext::CStringInfo si; - si = TextContext->getStringInfo(wordValue); - - // compute size of spaces + word - lineWidth += numSpaces * _SpaceWidth + si.StringWidth; - - currPos = wordEnd; - } - - // Update line width - if (lineWidth > maxWidth) - maxWidth = lineWidth; - - linePos = lineEnd+1; - } - - return (sint32)maxWidth; -} - -// *************************************************************************** -sint32 CViewText::getMinUsedW() const -{ - static const ucstring spaceOrLineFeedStr(" \n\t"); - sint32 maxWidth = 0; - - // Not multi line ? Same size than min - if (!_MultiLine) - return getMaxUsedW(); - - // If we can clip word, size of the largest word - if (_TextMode == ClipWord) - { - // No largest font parameter, return the font height - return _FontHeight; - } - // If we can't clip the words, return the size of the largest word - else if ((_TextMode == DontClipWord) || (_TextMode == Justified)) - { - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - TextContext->setHotSpot (UTextContext::BottomLeft); - TextContext->setShaded (_Shadow); - TextContext->setFontSize (_FontSize); - - // Current position in text - TCharPos currPos = 0; - while (currPos < _Text.length()) - { - // Current word - ucstring wordValue; - UTextContext::CStringInfo si; - TCharPos wordEnd; - - // Get word until a space or a \n is encountered - currPos = _Text.find_first_not_of(spaceOrLineFeedStr, currPos); - if (currPos == std::string::npos) - break; - wordEnd = _Text.find_first_of(spaceOrLineFeedStr, currPos); - if (wordEnd == std::string::npos) - wordEnd = _Text.length(); - - // Get the word - wordValue = _Text.substr(currPos, wordEnd - currPos); - - // Compute width of word - si = TextContext->getStringInfo(wordValue); - - // Larger ? - sint32 stringWidth = (sint32)si.StringWidth; - if (stringWidth>maxWidth) - maxWidth = stringWidth; - - // Next word - currPos = wordEnd; - } - } - - return maxWidth; -} - -// *************************************************************************** -void CViewText::onInvalidateContent() -{ - _InvalidTextContext= true; - invalidateCoords(); -} - -// *************************************************************************** -void CViewText::computeFontSize () -{ - NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(); - TextContext->setHotSpot (UTextContext::BottomLeft); - TextContext->setShaded (_Shadow); - TextContext->setFontSize (_FontSize); - - // Letter size - UTextContext::CStringInfo si = TextContext->getStringInfo(ucstring("|")); // for now we can't now that directly from UTextContext - _FontHeight = (uint) si.StringHeight + (_Shadow?1:0); - _FontLegHeight = (uint) si.StringLine + (_Shadow?1:0); - - // Space width - si = TextContext->getStringInfo(ucstring(" ")); - _SpaceWidth = si.StringWidth; - - // Font Width - si = TextContext->getStringInfo(ucstring("_")); - _FontWidth = (uint)si.StringWidth; -} - - -// *************************************************************************** -static inline bool isColorTag(const ucstring &s, uint index, uint textSize) -{ - // Format is @{RGBA} - if(s[index]=='@') - { - if( textSize>index+1 && s[index+1]=='{') - { - // verify 1st letter is a xdigit - if( textSize>index+2 && isxdigit(s[index+2])) - { - // We have good chance its a color tag. Do last verification - if(textSize>index+6 && s[index+6]=='}') - { - return true; - } - } - } - } - - return false; -} - -// *************************************************************************** -// isColorTag must be ok. -static inline CRGBA getColorTag(const ucstring &s, uint &index) -{ - // extract the color string: "FABC" - char tmpCol[5]; - for(uint i=0;i<4;i++) - tmpCol[i]= (char)s[index+2+i]; - tmpCol[4]= 0; - - // Convert to color - CRGBA color; - uint pCol; - sscanf(tmpCol, "%x", &pCol); - // Transform 4 bits to 8 bit. - color.R= (pCol>>12)&0xF; color.R+= color.R<<4; - color.G= (pCol>>8)&0xF; color.G+= color.G<<4; - color.B= (pCol>>4)&0xF; color.B+= color.B<<4; - color.A= (pCol)&0xF; color.A+= color.A<<4; - - // skip tag - index+= 7; - - return color; -} - - -// *************************************************************************** -const uint MaxTabDigit= 3; -static inline bool isTabTag(const ucstring &s, uint index, uint textSize) -{ - // Format is @{Tvalue}, where value ,1,2,3 digit. - if(s[index]=='@') - { - if( textSize>index+1 && s[index+1]=='{') - { - if( textSize>index+2 && s[index+2]=='T') - { - // We have good chance its a Tab tag. Do last verification - for(uint i=4;i<4+MaxTabDigit;i++) - { - if(textSize>index+i && s[index+i]=='}') - { - return true; - } - } - } - } - } - - return false; -} - -// *************************************************************************** -// isTabTag must be ok. -static inline sint getTabTag(const ucstring &s, uint &index) -{ - // extract the tab min X value - char tmpTab[MaxTabDigit+1]; - uint i; - for(i=0;iindex+1 && s[index+1]=='{') - { - if( textSize>index+2 && s[index+2]=='H') - { - uint i = 3; - while (textSize>index+i && s[index+i]!='}') - i++; - - if (textSize>index+i && s[index+i]=='}') - return true; - } - } - } - - return false; -} - -// *************************************************************************** -// isTooltipTag must be ok. -static inline ucstring getTooltipTag(const ucstring &s, uint &index) -{ - ucstring result; - uint i = 3; - while (s[index+i] != '}') - { - result += s[index+i]; - i++; - } - - // skip tag - index += i+1; - - return result; -} - - -// *************************************************************************** -void CViewText::buildFormatTagText(const ucstring &text, ucstring &textBuild, std::vector &formatTags, std::vector &tooltips) -{ - formatTags.clear(); - tooltips.clear(); - - // Build the text without the formatTags, and get the color tags separately - textBuild.reserve(text.size()); - uint textSize= (uint)text.size(); - // Must herit all the props from old tags. - CViewText::CFormatTag precTag; // set default. - precTag.Index = 0; - for (uint i = 0; i < textSize;) - { - if(isColorTag(text, i, textSize)) - { - // get old tag. - CViewText::CFormatTag ct= precTag; - // get new color and skip tag. - ct.Color= getColorTag(text, i); - ct.Index= (uint)textBuild.size(); - formatTags.push_back(ct); - } - else if(isTabTag(text, i, textSize)) - { - // get old tag. - CViewText::CFormatTag ct= precTag; - // get new Tab and skip tag. - ct.TabX= getTabTag(text, i); - ct.Index= (uint)textBuild.size(); - formatTags.push_back(ct); - } - else if(isTooltipTag(text, i, textSize)) - { - // get old tag. - CViewText::CFormatTag ct= precTag; - // get new Tab and skip tag. - ucstring uitt = getTooltipTag(text, i); - if (uitt.empty()) - { - ct.IndexTt= -1; - } - else - { - ct.IndexTt= (uint)tooltips.size(); - tooltips.push_back(uitt); - } - - ct.Index= (uint)textBuild.size(); - formatTags.push_back(ct); - } - else - { - bool lineFeed= text[i]=='\n'; - - // append to textBuild - textBuild+= text[i]; - ++i; - - // if \n, reset tabulations - if(lineFeed) - { - CViewText::CFormatTag ct= precTag; - ct.TabX= 0; - ct.Index= (uint)textBuild.size(); - formatTags.push_back(ct); - } - } - // bkup - if(!formatTags.empty()) - precTag= formatTags.back(); - } -} - - -// *************************************************************************** -void CViewText::setTextFormatTaged(const ucstring &text) -{ - - // to allow cache (avoid infinite recurse in updateCoords() in some case), compute in temp - ucstring tempText; - // static to avoid reallocation - static std::vector tempFormatTags; - static std::vector tempTooltips; - buildFormatTagText(text, tempText, tempFormatTags, tempTooltips); - setCase (tempText, _CaseMode); - - // compare Tag arrays - bool sameTagArray= false; - if(_FormatTags.size()==tempFormatTags.size()) - { - sameTagArray= true; - for(uint i=0;i<_FormatTags.size();i++) - { - if(!_FormatTags[i].sameTag(tempFormatTags[i])) - { - sameTagArray= false; - break; - } - } - } - - // test transformed text with current one - if(tempText!=_Text || !sameTagArray ) - { - // copy tags - _FormatTags= tempFormatTags; - // Copy to Text (preserve Memory) - contReset(_Text); - _Text= tempText; - - CInterfaceGroup *parent = getParent(); - - // Delete old dynamic tooltips - for (uint i=0 ; i<_Tooltips.size() ; ++i) - { - if (parent) - parent->delCtrl(_Tooltips[i]); - else - delete _Tooltips[i]; - } - _Tooltips.clear(); - - // Add new dynamic tooltips - for (uint i=0 ; isetId(_Id+"_tt"+toString(i)); - pTooltip->setAvoidResizeParent(avoidResizeParent()); - pTooltip->setRenderLayer(getRenderLayer()); - pTooltip->setDefaultContextHelp(CI18N::get(tempTooltips[i].toString())); - pTooltip->setParentPos(this); - pTooltip->setParentPosRef(Hotspot_BR); - pTooltip->setPosRef(Hotspot_BR); - pTooltip->setToolTipParent(CCtrlBase::TTWindow); - pTooltip->setToolTipParentPosRef(Hotspot_TTAuto); - pTooltip->setToolTipPosRef(Hotspot_TTAuto); - pTooltip->setActive(true); - - _Tooltips.push_back(pTooltip); - - if (parent) - { - pTooltip->setParent(parent); - parent->addCtrl(_Tooltips.back()); - } - } - - if (parent) - _Setuped = true; - else - _Setuped = false; - - invalidateContent (); - } - - // color format is available only if multilined - if (!_MultiLine) - nlwarning( toString("ViewText isn't multilined : uc_hardtext_format will not act as wanted !\n%s", text.toString().c_str()).c_str() ); -} - - -void CViewText::setSingleLineTextFormatTaged(const ucstring &text) -{ - // to allow cache (avoid infinite recurse in updateCoords() in some case), compute in temp - ucstring tempText; - static std::vector tempLetterColors; - static std::vector tempTooltips; - - // parse text - buildFormatTagText(text, tempText, tempLetterColors, tempTooltips); - setCase (tempText, _CaseMode); - - // decal for spaces (not inserted in VertexBuffer) - uint textIndex = 0; - uint spacesNb = 0; - for(uint i=0; icreateLetterColors(); - for(uint i=0; ipushLetterColor(formatTag.Index, formatTag.Color); - } - - // test transformed text with current one - if(tempText!=_Text || !_LetterColors || !_LetterColors->isSameLetterColors(letterColors)) - { - _LetterColors = letterColors; - - TextContext->setLetterColors(letterColors, _Index); - - // Copy to Text (preserve Memory) - contReset(_Text); - _Text= tempText; - invalidateContent (); - } - - // this color format is available only if not multilined - if (_MultiLine) - nlwarning( toString("ViewText is multilined : uc_hardtext_single_line_format will not act as wanted !\n%s", text.toString().c_str()).c_str() ); -} - - -// *************************************************************************** -bool CViewText::isFormatTagChange(uint textIndex, uint ctIndex) const -{ - if(ctIndex>=_FormatTags.size()) - return false; - // return true if the textIndex is > (eg if some skip with spaces) or = (common case) - return _FormatTags[ctIndex].Index <= textIndex; -} - -// *************************************************************************** -void CViewText::getFormatTagChange(uint textIndex, uint &ctIndex, CFormatInfo &wordFormat) const -{ - // support the possible case with multiple color tags with same textIndex. - while(ctIndex<_FormatTags.size() && _FormatTags[ctIndex].Index<=textIndex) - { - // Take the last tag. - wordFormat.Color= _FormatTags[ctIndex].Color; - wordFormat.TabX= _FormatTags[ctIndex].TabX; - wordFormat.IndexTt= _FormatTags[ctIndex].IndexTt; - // skip it. - ctIndex++; - } -} - - -// *************************************************************************** - -void CViewText::setCaseMode (TCaseMode caseMode) -{ - _CaseMode = caseMode; - setCase (_Text, _CaseMode); -} - -// *************************************************************************** - -TCaseMode CViewText::getCaseMode () const -{ - return _CaseMode; -} - -// *************************************************************************** - -void CViewText::resetTextIndex() -{ - _Index = 0xffffffff; - for(uint k = 0; k < _Lines.size(); ++k) - _Lines[k]->resetTextIndex(); -} - -// *************************************************************************** -void CViewText::setup() -{ - _Setuped= true; - - // Add dynamic tooltips - for (uint i=0 ; i<_Tooltips.size() ; ++i) - { - CInterfaceGroup *parent = getParent(); - if (parent) - { - _Tooltips[i]->setParent(parent); - parent->addCtrl(_Tooltips.back()); - } - } -} - -// *************************************************************************** -void CViewText::serial(NLMISC::IStream &f) -{ - #define SERIAL_UINT(val) { uint32 tmp = (uint32) val; f.serial(tmp); val = (uint) tmp; } - #define SERIAL_SINT(val) { sint32 tmp = (sint32) val; f.serial(tmp); val = (sint) tmp; } - CViewBase::serial(f); - SERIAL_SINT(_FontSize); - SERIAL_UINT(_FontWidth); - SERIAL_UINT(_FontHeight); - SERIAL_UINT(_FontLegHeight); - f.serial(_SpaceWidth); - f.serial(_Color); - f.serial(_Shadow); - f.serialEnum(_CaseMode); - f.serial(_ShadowColor); - f.serial(_LineMaxW); - f.serial(_SingleLineTextClamped); - f.serial(_MultiLine); - f.serial(_MultiLineMaxWOnly); - f.serial(_MultiLineClipEndSpace); - f.serial(_AutoClampOffset); - f.serialEnum(_TextMode); - SERIAL_SINT(_MultiLineSpace); - SERIAL_SINT(_LastMultiLineMaxW); - f.serial(_MultiMaxLine); - - bool hasTag = !_FormatTags.empty(); - f.serial(hasTag); - if (f.isReading()) - { - ucstring text; - f.serial(text); - if (hasTag) - { - if (_MultiLine) - { - setTextFormatTaged(text); - } - else - { - setSingleLineTextFormatTaged(text); - } - } - else - { - setText(text); - } - } - else - { - f.serial(_Text); - } - - #undef SERIAL_UINT - #undef SERIAL_SINT -} - - -// *************************************************************************** diff --git a/code/ryzom/client/src/interface_v3/view_text.h b/code/ryzom/client/src/interface_v3/view_text.h deleted file mode 100644 index 9fe54825b..000000000 --- a/code/ryzom/client/src/interface_v3/view_text.h +++ /dev/null @@ -1,413 +0,0 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#ifndef NL_VIEW_TEXT_H -#define NL_VIEW_TEXT_H - -#include "nel/gui/view_base.h" -#include "nel/gui/string_case.h" -#include "nel/3d/u_text_context.h" - -namespace NLGUI -{ - class CCtrlToolTip; -} - - -/** - * class implementing a text view - * \author Matthieu 'TrapII' Besson - * \author Nicolas Vizerie - * \author Nevrax France - * \date 2002 - */ -class CViewText : public CViewBase -{ -public: - enum TTextMode { ClipWord, DontClipWord, Justified }; -public: - - DECLARE_UI_CLASS(CViewText) - - - /// Constructor - CViewText (const TCtorParam ¶m); - - /// Constructor - CViewText (const std::string& id, const std::string Text="", sint FontSize=12, - NLMISC::CRGBA Color=NLMISC::CRGBA(255,255,255), bool Shadow=false); - - virtual ~CViewText(); - - CViewText &operator=(const CViewText &vt); - - void parseTextOptions (xmlNodePtr cur); - bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup); - virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } - - /// Updating - virtual void draw (); - void updateTextContext (); - virtual void checkCoords(); - virtual void updateCoords(); - virtual void onAddToGroup(); - - /// From CInterfaceElement - sint32 getMaxUsedW() const; - sint32 getMinUsedW() const; - - /// Accessors - - /// Set - - void setText (const ucstring &text); - void setFontSize (sint nFontSize); - void setColor (const NLMISC::CRGBA &color); - void setShadow (bool bShadow); - void setShadowColor (const NLMISC::CRGBA &color); - void setLineMaxW (sint nMaxW, bool invalidate=true); - void setMultiLine (bool bMultiLine); - void setMultiLineSpace (sint nMultiLineSpace); - void setMultiLineMaxWOnly (bool state); - void setMultiLineClipEndSpace (bool state); // use it for multiline edit box for instance - void setFirstLineX (uint firstLineX); - void setMultiMaxLine(uint l) { _MultiMaxLine = l; } - - // Force only a subset of letter to be displayed. Default is 0/0xFFFFFFFF - void enableStringSelection(uint start, uint end); - void disableStringSelection(); - - /// Get - - ucstring getText() const { return _Text; } - sint getFontSize() const; - NLMISC::CRGBA getColor() { return _Color; } - bool getShadow() { return _Shadow; } - NLMISC::CRGBA getShadowColor() { return _ShadowColor; } - sint getLineMaxW() const { return _LineMaxW; } - bool getMultiLine() const { return _MultiLine; } - sint getMultiLineSpace() const { return _MultiLineSpace; } - bool getMultiLineMaxWOnly() const { return _MultiLineMaxWOnly; } - uint32 getMultiMaxLine() const { return _MultiMaxLine; } - - // get current Hint font width, in pixels - uint getFontWidth() const; - // get current font height, in pixels - uint getFontHeight() const; - // get current font leg height, in pixels - uint getFontLegHeight() const; - // Set the display mode (supported with multiline only for now) - void setTextMode(TTextMode mode); - TTextMode getTextMode() const { return _TextMode; } - uint getNumLine() const; - uint getFirstLineX() const; - uint getLastLineW () const; - void setUnderlined (bool underlined) { _Underlined = underlined; } - bool getUnderlined () const { return _Underlined; } - // true if the viewText is a single line clamped. - bool isSingleLineTextClamped() const {return _SingleLineTextClamped;} - - // Character positions - - /** Get position of the ith character, position are relative to the BR corner of the text. - * \param lineEnd. When set to true, return the coordinate of the previous line if the index is at the start of a line. - * When looking at standard edit box, we see that if a line is split accross to line with no - * This also returns the height of the line - */ - void getCharacterPositionFromIndex(sint index, bool lineEnd, sint &x, sint &y, sint &height) const; - /** From a coordinate relative to the BR BR corner of the text, return the index of a character. - * If no character is found at the given position, the closest character is returned (first or last character, for the line or the whole text) - */ - void getCharacterIndexFromPosition(sint x, sint y, uint &index, bool &lineEnd) const; - /** From a character index, get the index of the line it belongs to, or -1 if the index is invalid - * \param cursorDisplayedAtEndOfPreviousLine true if the cursor is displayed at the end of the previous line that match its index - */ - sint getLineFromIndex(uint index, bool cursorDisplayedAtEndOfPreviousLine = true) const; - /// From a line number, get the character at which it starts, or -1 if invalid - sint getLineStartIndex(uint line) const; - /// From a line number, get the character at which it ends (not including any '\n' ), or -1 if invalid - void getLineEndIndex(uint line, sint &index, bool &endOfPreviousLine) const; - - std::string getHardText() const { std::string result; _Text.toString (result); return result; } - void setHardText (const std::string &ht); - - std::string getColorAsString() const; - void setColorAsString(const std::string &ht); - - NLMISC::CRGBA getColorRGBA() const; - void setColorRGBA(NLMISC::CRGBA col); - - virtual sint32 getAlpha() const { return _Color.A; } - virtual void setAlpha (sint32 a) { _ShadowColor.A = _Color.A = (uint8)a; } - - /** Setup a Text with Format Tags. Text is store without color/format tags, and special array is allocated for Format association - */ - void setTextFormatTaged(const ucstring &text); - - void setSingleLineTextFormatTaged(const ucstring &text); - - // Remove end space - void removeEndSpaces(); - - // Reset the text index because the text context has changed - void resetTextIndex(); - - // Case mode - void setCaseMode (TCaseMode caseMode); - TCaseMode getCaseMode () const; - - // OverExtendViewText - void setOverExtendViewText(bool state) {_OverExtendViewText= state;} - bool getOverExtendViewText() const {return _OverExtendViewText;} - - // OverExtendViewTextUseParentRect - void setOverExtendViewTextUseParentRect(bool state) {_OverExtendViewTextUseParentRect= state;} - bool getOverExtendViewTextUseParentRect() const {return _OverExtendViewTextUseParentRect;} - - // see if text ellipsis if done at right side of the text - bool isClampRight() const { return _ClampRight; } - - int luaSetLineMaxW(CLuaState &ls); - - REFLECT_EXPORT_START(CViewText, CViewBase) - REFLECT_STRING("hardtext", getHardText, setHardText); - REFLECT_UCSTRING("uc_hardtext", getText, setText); - REFLECT_UCSTRING("uc_hardtext_format", getText, setTextFormatTaged); - REFLECT_UCSTRING("uc_hardtext_single_line_format", getText, setSingleLineTextFormatTaged); - REFLECT_STRING ("color", getColorAsString, setColorAsString); - REFLECT_RGBA ("color_rgba", getColorRGBA, setColorRGBA); - REFLECT_SINT32 ("alpha", getAlpha, setAlpha); - REFLECT_BOOL ("overExtendViewText", getOverExtendViewText, setOverExtendViewText); - REFLECT_BOOL ("overExtendViewTextUseParentRect", getOverExtendViewTextUseParentRect, setOverExtendViewTextUseParentRect); - REFLECT_LUA_METHOD("setLineMaxW", luaSetLineMaxW); - REFLECT_EXPORT_END - - - virtual void serial(NLMISC::IStream &f); - -protected: - - /// Text to display. - ucstring _Text; - /// index of the computed String associated to this text control - uint _Index; - /// info on the computed String associated to this text control - NL3D::UTextContext::CStringInfo _Info; - /// the font size - sint _FontSize; - // width of the font in pixel. Just a Hint for tabing format (computed with '_') - uint _FontWidth; - // height of the font in pixel. - // use getFontHeight - uint _FontHeight; - uint _FontLegHeight; - float _SpaceWidth; - /// the text color - NLMISC::CRGBA _Color; - /// the shadow mode - bool _Shadow; - /// the case mode - TCaseMode _CaseMode; - /// the text shadow color - NLMISC::CRGBA _ShadowColor; - /// Is the line (under p loop) should be considered at bottom (if false bottom is under p leg) - /// maxw for the line/multiline - sint32 _LineMaxW; - /// For single line, true if the text is clamped (ie displayed with "...") - bool _SingleLineTextClamped; - - /// Multiple lines handling - bool _MultiLine; - bool _MultiLineMaxWOnly; - bool _MultiLineClipEndSpace; - uint8 _AutoClampOffset; - TTextMode _TextMode; - sint _MultiLineSpace; - sint _LastMultiLineMaxW; - uint32 _MultiMaxLine; - - - /// FormatTag handling - struct CFormatInfo - { - // The color to change - NLMISC::CRGBA Color; - // The Tabulation to apply, in number of "_" characters. - uint TabX; - // Index in vector - sint IndexTt; - - CFormatInfo() - { - Color= NLMISC::CRGBA::White; - TabX= 0; - IndexTt = -1; - } - - bool operator==(const CFormatInfo &o) const {return Color==o.Color && TabX==o.TabX && IndexTt==o.IndexTt;} - bool operator!=(const CFormatInfo &o) const {return !operator==(o);} - }; - struct CFormatTag : public CFormatInfo - { - uint Index; - - // compare 2 tags, not a tag and a CFormatInfo - bool sameTag(const CFormatTag &o) const - { - return CFormatInfo::operator==(o) && Index==o.Index; - } - }; - std::vector _FormatTags; - - /// Get the current maxW for multiline, accordgin to parent and _MultiLineOptionMaxW - sint getCurrentMultiLineMaxW() const; - - - - - NL3D::ULetterColors * _LetterColors; - -private: - // A word in a line - class CWord - { - public: - // default ctor - CWord(uint numSpaces = 0) : Index(0), NumSpaces(numSpaces) {} - ucstring Text; - uint Index; // index of the info for this word - NL3D::UTextContext::CStringInfo Info; - uint NumSpaces; // number of spaces before this word - // The specialized color/format of this word. White if none - CFormatInfo Format; - public: - // build from a string, using the current text context - void build(const ucstring &text, uint numSpaces= 0); - }; - typedef std::vector TWordVect; - - // A line of text (which is made of one word with space, or of several words with no spaces in them) - class CLine : public NLMISC::CRefCount - { - public: - // ctor - CLine(); - // Clear the line & remove text contexts - void clear(); - // Add a new word (and its context) in the line + a number of spaces to append at the end of the line - void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, uint fontWidth); - void addWord(const CWord &word, uint fontWidth); - uint getNumWords() const { return (uint)_Words.size(); } - CWord &getWord(uint index) { return _Words[index]; } - float getSpaceWidth() const { return _SpaceWidth; } - void setSpaceWidth(float width) { _SpaceWidth = width; } - // Get the number of chars in the line, not counting the end spaces, but couting the spaces in words - uint getNumChars() const { return _NumChars; } - // Get the total number of spaces between words (not including those in words, but there should not be if text is justified) - uint getNumSpaces() const { return _NumSpaces; } - float getStringLine() const { return _StringLine; } - float getWidthWithoutSpaces() const { return _WidthWithoutSpaces; } - // get total width including spaces, but not including end spaces - float getWidth() const { return _WidthWithoutSpaces + _SpaceWidth * _NumSpaces; } - // Get the number of spaces at the end of the line - void setEndSpaces(uint numSpaces) { _EndSpaces = numSpaces; } - // Set the number of spaces at the end of the line - uint getEndSpaces() const { return _EndSpaces; } - // Test if there's a line feed at the end of the line - bool getLF() const { return _HasLF; } - void setLF(bool lf) { _HasLF = lf; } - void resetTextIndex(); - private: - TWordVect _Words; - uint _NumChars; - uint _NumSpaces; - float _SpaceWidth; // width of a space, in pixels (used with multispace alignment) - float _StringLine; - float _WidthWithoutSpaces; // width without space (see the Field NumSpaces in the CWord class). - // NB : space inserted inside a word are counted, however! - uint _EndSpaces; // spaces at the end of the line - bool _HasLF; // a linefeed is at end of line (no breaking due to line full) - }; - /// NB : we keep pointers on lines (each line contains a vector, that we don't want to be copied, and this occurs as the vector of lines grows..) - - typedef NLMISC::CSmartPtr TLineSPtr; - typedef std::vector TLinePtVect; -private: - /** Data of the updated text for multiline. It is built from the _Text field in the updateTextContext member function, - * and is used to perform the draw - */ - TLinePtVect _Lines; - - /// if true, and if the view text is isSingleLineTextClamped(), then an over will be drawn, with the text - bool _OverExtendViewText : 1; - /// if true and _OverExtendViewText true too, use the parent rectangle to know if must display the over or not - bool _OverExtendViewTextUseParentRect : 1; - /// Letter selection handling - bool _AutoClamp : 1; - bool _ClampRight : 1; - bool _TextSelection : 1; - bool _InvalidTextContext : 1; - bool _Underlined : 1; - bool _ContinuousUpdate : 1; - bool _Setuped : 1; - - uint _TextSelectionStart; - uint _TextSelectionEnd; - - // First line X coordinate - uint _FirstLineX; - - /// Dynamic tooltips - std::vector _Tooltips; - - -private: - void setup (); - void setupDefault (); - - void setStringSelectionSkipingSpace(uint stringId, const ucstring &text, sint charStart, sint charEnd); - -// void pushString(const ucstring &str, bool deleteSpaceAtStart = false); - - /// \from CInterfaceElement - void onInvalidateContent(); - - // may append a new line, and append a word to the last line (no spaces) - void flushWordInLine(ucstring &ucCurrentWord, bool &linePushed, const CFormatInfo &wordFormat); - // Clear all the lines and free their datas - void clearLines(); - // Update in the case of a multiline text - void updateTextContextMultiLine(uint nMaxWidth); - // Update in the case of a multiline text with justification - void updateTextContextMultiLineJustified(uint nMaxWidth, bool expandSpaces); - // Recompute font size info - void computeFontSize (); - - // used for "donctClipWord" case in updateTextContextMultiLineJustified(). currLine is reseted - void addDontClipWordLine(std::vector &currLine); - - // FormatTag build. - static void buildFormatTagText(const ucstring &text, ucstring &textBuild, std::vector &formatTags, std::vector &tooltips); - // FormatTag parsing. - bool isFormatTagChange(uint textIndex, uint ctIndex) const; - void getFormatTagChange(uint textIndex, uint &ctIndex, CFormatInfo &wordFormat) const; -}; - -#endif // NL_VIEW_TEXT_H - -/* End of view_text.h */ diff --git a/code/ryzom/client/src/interface_v3/view_text_formated.h b/code/ryzom/client/src/interface_v3/view_text_formated.h index 4e60e3f1f..0f8c2d4c0 100644 --- a/code/ryzom/client/src/interface_v3/view_text_formated.h +++ b/code/ryzom/client/src/interface_v3/view_text_formated.h @@ -19,7 +19,7 @@ #ifndef VIEW_TEXT_FORMATED_H #define VIEW_TEXT_FORMATED_H -#include "view_text.h" +#include "nel/gui/view_text.h" /** The same as a view text id, but with some display option * The input is a formated string, every character is copied, but subsitution is done for each character preceded by $ diff --git a/code/ryzom/client/src/interface_v3/view_text_id.h b/code/ryzom/client/src/interface_v3/view_text_id.h index 91d6b5f6e..f976791be 100644 --- a/code/ryzom/client/src/interface_v3/view_text_id.h +++ b/code/ryzom/client/src/interface_v3/view_text_id.h @@ -20,7 +20,7 @@ #define NL_VIEW_TEXT_ID_H #include "nel/misc/types_nl.h" -#include "view_text.h" +#include "nel/gui/view_text.h" namespace NLMISC{ class CCDBNodeLeaf; diff --git a/code/ryzom/client/src/login.cpp b/code/ryzom/client/src/login.cpp index 0b96b0782..842267e67 100644 --- a/code/ryzom/client/src/login.cpp +++ b/code/ryzom/client/src/login.cpp @@ -37,7 +37,7 @@ #include "interface_v3/input_handler_manager.h" #include "interface_v3/group_editbox.h" #include "interface_v3/group_quick_help.h" -#include "interface_v3/view_text.h" +#include "nel/gui/view_text.h" #include "nel/gui/ctrl_button.h" #include "interface_v3/ctrl_text_button.h" #include "sound_manager.h"