diff options
Diffstat (limited to 'indra/llui/lltextbase.h')
-rw-r--r-- | indra/llui/lltextbase.h | 1512 |
1 files changed, 758 insertions, 754 deletions
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index f5adb0dd86..d8e9027bae 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -1,754 +1,758 @@ -/** - * @file lltextbase.h - * @author Martin Reddy - * @brief The base class of text box/editor, providing Url handling support - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLTEXTBASE_H -#define LL_LLTEXTBASE_H - -#include "v4color.h" -#include "lleditmenuhandler.h" -#include "llspellcheckmenuhandler.h" -#include "llstyle.h" -#include "llkeywords.h" -#include "llpanel.h" - -#include <string> -#include <vector> -#include <set> - -#include <boost/signals2.hpp> - -class LLScrollContainer; -class LLContextMenu; -class LLUrlMatch; - -/// -/// A text segment is used to specify a subsection of a text string -/// that should be formatted differently, such as a hyperlink. It -/// includes a start/end offset from the start of the string, a -/// style to render with, an optional tooltip, etc. -/// -class LLTextSegment -: public LLRefCount, - public LLMouseHandler -{ -public: - LLTextSegment(S32 start, S32 end) - : mStart(start), - mEnd(end) - {} - virtual ~LLTextSegment(); - bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; - - virtual bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const; - virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; - - /** - * Get number of chars that fit into free part of current line. - * - * @param num_pixels - maximum width of rect - * @param segment_offset - symbol in segment we start processing line from - * @param line_offset - symbol in line after which segment starts - * @param max_chars - limit of symbols that will fit in current line - * @param line_ind - index of not word-wrapped string inside segment for multi-line segments. - * Two string separated by word-wrap will have same index. - * @return number of chars that will fit into current line - */ - virtual S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const; - virtual void updateLayout(const class LLTextBase& editor); - virtual F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); - virtual bool canEdit() const; - virtual void unlinkFromDocument(class LLTextBase* editor); - virtual void linkToDocument(class LLTextBase* editor); - - virtual const LLColor4& getColor() const; - //virtual void setColor(const LLColor4 &color); - virtual LLStyleConstSP getStyle() const; - virtual void setStyle(LLStyleConstSP style); - virtual void setToken( LLKeywordToken* token ); - virtual LLKeywordToken* getToken() const; - virtual void setToolTip(const std::string& tooltip); - virtual void dump() const; - - // LLMouseHandler interface - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMiddleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMiddleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleRightMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleDoubleClick(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleScrollWheel(S32 x, S32 y, S32 clicks); - /*virtual*/ bool handleScrollHWheel(S32 x, S32 y, S32 clicks); - /*virtual*/ bool handleToolTip(S32 x, S32 y, MASK mask); - /*virtual*/ const std::string& getName() const; - /*virtual*/ void onMouseCaptureLost(); - /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const; - /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const; - /*virtual*/ bool hasMouseCapture(); - - S32 getStart() const { return mStart; } - void setStart(S32 start) { mStart = start; } - S32 getEnd() const { return mEnd; } - void setEnd( S32 end ) { mEnd = end; } - -protected: - S32 mStart; - S32 mEnd; -}; - -class LLNormalTextSegment : public LLTextSegment -{ -public: - LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor ); - LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, bool is_visible = true); - virtual ~LLNormalTextSegment(); - - /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const; - /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; - /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const; - /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); - /*virtual*/ bool canEdit() const { return true; } - /*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); } - /*virtual*/ LLStyleConstSP getStyle() const { return mStyle; } - /*virtual*/ void setStyle(LLStyleConstSP style) { mStyle = style; } - /*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; } - /*virtual*/ LLKeywordToken* getToken() const { return mToken; } - /*virtual*/ bool getToolTip( std::string& msg ) const; - /*virtual*/ void setToolTip(const std::string& tooltip); - /*virtual*/ void dump() const; - - /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleToolTip(S32 x, S32 y, MASK mask); - -protected: - F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRectf rect); - - virtual const LLWString& getWText() const; - virtual const S32 getLength() const; - -protected: - class LLTextBase& mEditor; - LLStyleConstSP mStyle; - S32 mFontHeight; - LLKeywordToken* mToken; - std::string mTooltip; - boost::signals2::connection mImageLoadedConnection; -}; - -// This text segment is the same as LLNormalTextSegment, the only difference -// is that LLNormalTextSegment draws value of LLTextBase (LLTextBase::getWText()), -// but LLLabelTextSegment draws label of the LLTextBase (LLTextBase::mLabel) -class LLLabelTextSegment : public LLNormalTextSegment -{ -public: - LLLabelTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor ); - LLLabelTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, bool is_visible = true); - -protected: - - /*virtual*/ const LLWString& getWText() const; - /*virtual*/ const S32 getLength() const; -}; - -// Text segment that represents a single emoji character that has a different style (=font size) than the rest of -// the document it belongs to -class LLEmojiTextSegment : public LLNormalTextSegment -{ -public: - LLEmojiTextSegment(LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor); - LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end, LLTextBase& editor, bool is_visible = true); - - bool canEdit() const override { return false; } - bool handleToolTip(S32 x, S32 y, MASK mask) override; -}; - -// Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment) -class LLOnHoverChangeableTextSegment : public LLNormalTextSegment -{ -public: - LLOnHoverChangeableTextSegment( LLStyleConstSP style, LLStyleConstSP normal_style, S32 start, S32 end, LLTextBase& editor ); - /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); - /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask); -protected: - // Style used for text when mouse pointer is over segment - LLStyleConstSP mHoveredStyle; - // Style used for text when mouse pointer is outside segment - LLStyleConstSP mNormalStyle; - -}; - -class LLIndexSegment : public LLTextSegment -{ -public: - LLIndexSegment() : LLTextSegment(0, 0) {} -}; - -class LLInlineViewSegment : public LLTextSegment -{ -public: - struct Params : public LLInitParam::Block<Params> - { - Mandatory<LLView*> view; - Optional<bool> force_newline; - Optional<S32> left_pad, - right_pad, - bottom_pad, - top_pad; - }; - - LLInlineViewSegment(const Params& p, S32 start, S32 end); - ~LLInlineViewSegment(); - /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const; - /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const; - /*virtual*/ void updateLayout(const class LLTextBase& editor); - /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); - /*virtual*/ bool canEdit() const { return false; } - /*virtual*/ void unlinkFromDocument(class LLTextBase* editor); - /*virtual*/ void linkToDocument(class LLTextBase* editor); - -private: - S32 mLeftPad; - S32 mRightPad; - S32 mTopPad; - S32 mBottomPad; - LLView* mView; - bool mForceNewLine; -}; - -class LLLineBreakTextSegment : public LLTextSegment -{ -public: - - LLLineBreakTextSegment(LLStyleConstSP style,S32 pos); - LLLineBreakTextSegment(S32 pos); - ~LLLineBreakTextSegment(); - /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const; - S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const; - F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); - -private: - S32 mFontHeight; -}; - -class LLImageTextSegment : public LLTextSegment -{ -public: - LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor); - ~LLImageTextSegment(); - /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const; - S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 char_offset, S32 max_chars, S32 line_ind) const; - F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); - - /*virtual*/ bool handleToolTip(S32 x, S32 y, MASK mask); - /*virtual*/ void setToolTip(const std::string& tooltip); - -private: - class LLTextBase& mEditor; - LLStyleConstSP mStyle; - -protected: - std::string mTooltip; -}; - -typedef LLPointer<LLTextSegment> LLTextSegmentPtr; - -/// -/// The LLTextBase class provides a base class for all text fields, such -/// as LLTextEditor and LLTextBox. It implements shared functionality -/// such as Url highlighting and opening. -/// -class LLTextBase -: public LLUICtrl, - protected LLEditMenuHandler, - public LLSpellCheckMenuHandler, - public ll::ui::SearchableControl -{ -public: - friend class LLTextSegment; - friend class LLNormalTextSegment; - friend class LLUICtrlFactory; - - typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t; - typedef boost::signals2::signal<bool (const LLUUID& blocked_id, const std::string from)> is_blocked_signal_t; - - struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams> - { - Alternative<F32> multiple; - Alternative<S32> pixels; - LineSpacingParams(); - }; - - struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> - { - Optional<LLUIColor> cursor_color, - text_color, - text_readonly_color, - text_tentative_color, - bg_readonly_color, - bg_writeable_color, - bg_focus_color, - text_selected_color, - bg_selected_color; - - Optional<bool> bg_visible, - border_visible, - track_end, - read_only, - skip_link_underline, - spellcheck, - allow_scroll, - plain_text, - wrap, - use_ellipses, - use_color, - parse_urls, - force_urls_external, - parse_highlights, - clip, - clip_partial, - trusted_content, - always_show_icons; - - Optional<S32> v_pad, - h_pad; - - - Optional<LineSpacingParams> - line_spacing; - - Optional<S32> max_text_length; - - Optional<LLFontGL::ShadowType> font_shadow; - - Optional<LLFontGL::VAlign> text_valign; - - Params(); - }; - - // LLMouseHandler interface - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask) override; - /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask) override; - /*virtual*/ bool handleMiddleMouseDown(S32 x, S32 y, MASK mask) override; - /*virtual*/ bool handleMiddleMouseUp(S32 x, S32 y, MASK mask) override; - /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask) override; - /*virtual*/ bool handleRightMouseUp(S32 x, S32 y, MASK mask) override; - /*virtual*/ bool handleDoubleClick(S32 x, S32 y, MASK mask) override; - /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask) override; - /*virtual*/ bool handleScrollWheel(S32 x, S32 y, S32 clicks) override; - /*virtual*/ bool handleToolTip(S32 x, S32 y, MASK mask) override; - - // LLView interface - /*virtual*/ const std::string getToolTip() const override; - /*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true) override; - /*virtual*/ void draw() override; - - // LLUICtrl interface - /*virtual*/ bool acceptsTextInput() const override { return !mReadOnly; } - /*virtual*/ void setColor(const LLColor4& c) override; - virtual void setReadOnlyColor(const LLColor4 &c); - /*virtual*/ void onVisibilityChange(bool new_visibility) override; - - /*virtual*/ void setValue(const LLSD& value) override; - /*virtual*/ LLTextViewModel* getViewModel() const override; - - // LLEditMenuHandler interface - /*virtual*/ bool canDeselect() const override; - /*virtual*/ void deselect() override; - - virtual void onFocusReceived() override; - virtual void onFocusLost() override; - - void setParseHTML(bool parse_html) { mParseHTML = parse_html; } - - // LLSpellCheckMenuHandler overrides - /*virtual*/ bool getSpellCheck() const override; - - /*virtual*/ const std::string& getSuggestion(U32 index) const override; - /*virtual*/ U32 getSuggestionCount() const override; - /*virtual*/ void replaceWithSuggestion(U32 index) override; - - /*virtual*/ void addToDictionary() override; - /*virtual*/ bool canAddToDictionary() const override; - - /*virtual*/ void addToIgnore() override; - /*virtual*/ bool canAddToIgnore() const override; - - // Spell checking helper functions - std::string getMisspelledWord(U32 pos) const; - bool isMisspelledWord(U32 pos) const; - void onSpellCheckSettingsChange(); - virtual void onSpellCheckPerformed(){} - - // used by LLTextSegment layout code - bool getWordWrap() { return mWordWrap; } - bool getUseEllipses() { return mUseEllipses; } - bool getUseColor() { return mUseColor; } - bool truncate(); // returns true of truncation occurred - - bool isContentTrusted() {return mTrustedContent;} - void setContentTrusted(bool trusted_content) { mTrustedContent = trusted_content; } - - // TODO: move into LLTextSegment? - void createUrlContextMenu(S32 x, S32 y, const std::string &url); // create a popup context menu for the given Url - - // Text accessors - // TODO: add optional style parameter - virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style - virtual std::string getText() const; - void setMaxTextLength(S32 length) { mMaxTextByteLength = length; } - S32 getMaxTextLength() { return mMaxTextByteLength; } - - // wide-char versions - void setWText(const LLWString& text); - const LLWString& getWText() const; - - void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params()); - - void setLabel(const LLStringExplicit& label); - /*virtual*/ bool setLabelArg(const std::string& key, const LLStringExplicit& text) override; - - const std::string& getLabel() { return mLabel.getString(); } - const LLWString& getWlabel() { return mLabel.getWString();} - - void setLastSegmentToolTip(const std::string &tooltip); - - /** - * If label is set, draws text label (which is LLLabelTextSegment) - * that is visible when no user text provided - */ - void resetLabel(); - - void setFont(const LLFontGL* font); - - // force reflow of text - void needsReflow(S32 index = 0); - - S32 getLength() const { return getWText().length(); } - S32 getLineCount() const { return mLineInfoList.size(); } - S32 removeFirstLine(); // returns removed length - - void addDocumentChild(LLView* view); - void removeDocumentChild(LLView* view); - const LLView* getDocumentView() const { return mDocumentView; } - LLRect getVisibleTextRect() const { return mVisibleTextRect; } - LLRect getTextBoundingRect(); - LLRect getVisibleDocumentRect() const; - - S32 getVPad() { return mVPad; } - S32 getHPad() { return mHPad; } - F32 getLineSpacingMult() { return mLineSpacingMult; } - S32 getLineSpacingPixels() { return mLineSpacingPixels; } // only for multiline - - S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, bool round, bool hit_past_end_of_line = true) const; - LLRect getLocalRectFromDocIndex(S32 pos) const; - LLRect getDocRectFromDocIndex(S32 pos) const; - - void setReadOnly(bool read_only) { mReadOnly = read_only; } - bool getReadOnly() { return mReadOnly; } - - void setSkipLinkUnderline(bool skip_link_underline) { mSkipLinkUnderline = skip_link_underline; } - bool getSkipLinkUnderline() { return mSkipLinkUnderline; } - - void setParseURLs(bool parse_urls) { mParseHTML = parse_urls; } - - void setPlainText(bool value) { mPlainText = value;} - bool getPlainText() const { return mPlainText; } - - // cursor manipulation - bool setCursor(S32 row, S32 column); - bool setCursorPos(S32 cursor_pos, bool keep_cursor_offset = false); - void startOfLine(); - void endOfLine(); - void startOfDoc(); - void endOfDoc(); - void changePage( S32 delta ); - void changeLine( S32 delta ); - - bool scrolledToStart(); - bool scrolledToEnd(); - - const LLFontGL* getFont() const { return mFont; } - - virtual void appendLineBreakSegment(const LLStyle::Params& style_params); - virtual void appendImageSegment(const LLStyle::Params& style_params); - virtual void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo); - boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb); - boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb); - boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb); - - void setWordWrap(bool wrap); - LLScrollContainer* getScrollContainer() const { return mScroller; } - -protected: - // protected member variables - // List of offsets and segment index of the start of each line. Always has at least one node (0). - struct line_info - { - line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num); - S32 mDocIndexStart; - S32 mDocIndexEnd; - LLRect mRect; - S32 mLineNum; // actual line count (ignoring soft newlines due to word wrap) - }; - typedef std::vector<line_info> line_list_t; - - // helper structs - struct compare_bottom - { - bool operator()(const S32& a, const line_info& b) const; - bool operator()(const line_info& a, const S32& b) const; - bool operator()(const line_info& a, const line_info& b) const; - }; - struct compare_top - { - bool operator()(const S32& a, const line_info& b) const; - bool operator()(const line_info& a, const S32& b) const; - bool operator()(const line_info& a, const line_info& b) const; - }; - struct line_end_compare; - typedef std::vector<LLTextSegmentPtr> segment_vec_t; - - // Abstract inner base class representing an undoable editor command. - // Concrete sub-classes can be defined for operations such as insert, remove, etc. - // Used as arguments to the execute() method below. - class TextCmd - { - public: - TextCmd( S32 pos, bool group_with_next, LLTextSegmentPtr segment = LLTextSegmentPtr() ) - : mPos(pos), - mGroupWithNext(group_with_next) - { - if (segment.notNull()) - { - mSegments.push_back(segment); - } - } - virtual ~TextCmd() {} - virtual bool execute(LLTextBase* editor, S32* delta) = 0; - virtual S32 undo(LLTextBase* editor) = 0; - virtual S32 redo(LLTextBase* editor) = 0; - virtual bool canExtend(S32 pos) const { return false; } - virtual void blockExtensions() {} - virtual bool extendAndExecute( LLTextBase* editor, S32 pos, llwchar c, S32* delta ) { llassert(0); return 0; } - virtual bool hasExtCharValue( llwchar value ) const { return false; } - - // Defined here so they can access protected LLTextEditor editing methods - S32 insert(LLTextBase* editor, S32 pos, const LLWString &wstr) { return editor->insertStringNoUndo( pos, wstr, &mSegments ); } - S32 remove(LLTextBase* editor, S32 pos, S32 length) { return editor->removeStringNoUndo( pos, length ); } - S32 overwrite(LLTextBase* editor, S32 pos, llwchar wc) { return editor->overwriteCharNoUndo(pos, wc); } - - S32 getPosition() const { return mPos; } - bool groupWithNext() const { return mGroupWithNext; } - - protected: - const S32 mPos; - bool mGroupWithNext; - segment_vec_t mSegments; - }; - - struct compare_segment_end - { - bool operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const; - }; - typedef std::multiset<LLTextSegmentPtr, compare_segment_end> segment_set_t; - - // member functions - LLTextBase(const Params &p); - virtual ~LLTextBase(); - void initFromParams(const Params& p); - virtual void beforeValueChange(); - virtual void onValueChange(S32 start, S32 end); - virtual bool useLabel() const; - - // draw methods - virtual void drawSelectionBackground(); // draws the black box behind the selected text - void drawCursor(); - void drawText(); - - // modify contents - S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted - S32 removeStringNoUndo(S32 pos, S32 length); - S32 overwriteCharNoUndo(S32 pos, llwchar wc); - void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep, bool underline_on_hover_only = false); - - - // manage segments - void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const; - void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp ); - LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line = true); - segment_set_t::iterator getEditableSegIterContaining(S32 index); - segment_set_t::const_iterator getEditableSegIterContaining(S32 index) const; - segment_set_t::iterator getSegIterContaining(S32 index); - segment_set_t::const_iterator getSegIterContaining(S32 index) const; - void clearSegments(); - void createDefaultSegment(); - virtual void updateSegments(); - void insertSegment(LLTextSegmentPtr segment_to_insert); - const LLStyle::Params& getStyleParams(); - - // manage lines - S32 getLineStart( S32 line ) const; - S32 getLineEnd( S32 line ) const; - S32 getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap = true) const; - S32 getLineOffsetFromDocIndex( S32 doc_index, bool include_wordwrap = true) const; - S32 getFirstVisibleLine() const; - std::pair<S32, S32> getVisibleLines(bool fully_visible = false); - S32 getLeftOffset(S32 width); - void reflow(); - - // cursor - void updateCursorXPos(); - void setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool keep_cursor_offset=false ); - S32 getEditableIndex(S32 index, bool increasing_direction); // constraint cursor to editable segments of document - void resetCursorBlink() { mCursorBlinkTimer.reset(); } - void updateScrollFromCursor(); - - // text selection - bool hasSelection() const { return (mSelectionStart !=mSelectionEnd); } - void startSelection(); - void endSelection(); - - // misc - void updateRects(); - void needsScroll() { mScrollNeeded = true; } - - struct URLLabelCallback; - // Replace a URL with a new icon and label, for example, when - // avatar names are looked up. - void replaceUrl(const std::string &url, const std::string &label, const std::string& icon); - - void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params()); - void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false); - S32 normalizeUri(std::string& uri); - -protected: - // virtual - std::string _getSearchText() const override - { - return mLabel.getString() + getToolTip(); - } - - std::vector<LLRect> getSelectionRects(); - -protected: - // text segmentation and flow - segment_set_t mSegments; - line_list_t mLineInfoList; - LLRect mVisibleTextRect; // The rect in which text is drawn. Excludes borders. - LLRect mTextBoundingRect; - - // default text style - LLStyle::Params mStyle; - bool mStyleDirty; - const LLFontGL* mFont; - const LLFontGL::ShadowType mFontShadow; - - // colors - LLUIColor mCursorColor; - LLUIColor mFgColor; - LLUIColor mReadOnlyFgColor; - LLUIColor mTentativeFgColor; - LLUIColor mWriteableBgColor; - LLUIColor mReadOnlyBgColor; - LLUIColor mFocusBgColor; - LLUIColor mTextSelectedColor; - LLUIColor mSelectedBGColor; - - // cursor - S32 mCursorPos; // I-beam is just after the mCursorPos-th character. - S32 mDesiredXPixel; // X pixel position where the user wants the cursor to be - LLFrameTimer mCursorBlinkTimer; // timer that controls cursor blinking - - // selection - S32 mSelectionStart; - S32 mSelectionEnd; - LLTimer mTripleClickTimer; - - bool mIsSelecting; // Are we in the middle of a drag-select? - - // spell checking - bool mSpellCheck; - S32 mSpellCheckStart; - S32 mSpellCheckEnd; - LLTimer mSpellCheckTimer; - std::list<std::pair<U32, U32> > mMisspellRanges; - std::vector<std::string> mSuggestionList; - - // configuration - S32 mHPad; // padding on left of text - S32 mVPad; // padding above text - LLFontGL::HAlign mHAlign; // horizontal alignment of the document in its entirety - LLFontGL::VAlign mVAlign; // vertical alignment of the document in its entirety - LLFontGL::VAlign mTextVAlign; // vertical alignment of a text segment within a single line of text - F32 mLineSpacingMult; // multiple of line height used as space for a single line of text (e.g. 1.5 to get 50% padding) - S32 mLineSpacingPixels; // padding between lines - bool mBorderVisible; - bool mParseHTML; // make URLs interactive - bool mForceUrlsExternal; // URLs from this textbox will be opened in external browser - bool mParseHighlights; // highlight user-defined keywords - bool mWordWrap; - bool mUseEllipses; - bool mUseColor; - bool mTrackEnd; // if true, keeps scroll position at end of document during resize - bool mReadOnly; - bool mBGVisible; // render background? - bool mClip; // clip text to widget rect - bool mClipPartial; // false if we show lines that are partially inside bounding rect - bool mTrustedContent; // if false, does not allow to execute SURL links from this editor - bool mPlainText; // didn't use Image or Icon segments - bool mAutoIndent; - S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes - bool mSkipTripleClick; - bool mAlwaysShowIcons; - - bool mSkipLinkUnderline; - - // support widgets - LLHandle<LLContextMenu> mPopupMenuHandle; - LLView* mDocumentView; - LLScrollContainer* mScroller; - - // transient state - S32 mReflowIndex; // index at which to start reflow. S32_MAX indicates no reflow needed. - bool mScrollNeeded; // need to change scroll region because of change to cursor position - S32 mScrollIndex; // index of first character to keep visible in scroll region - - // Fired when a URL link is clicked - commit_signal_t* mURLClickSignal; - - // Used to check if user with given ID is avatar's friend - is_friend_signal_t* mIsFriendSignal; - is_blocked_signal_t* mIsObjectBlockedSignal; - - LLUIString mLabel; // text label that is visible when no user text provided -}; - -#endif +/**
+ * @file lltextbase.h
+ * @author Martin Reddy
+ * @brief The base class of text box/editor, providing Url handling support
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEXTBASE_H
+#define LL_LLTEXTBASE_H
+
+#include "v4color.h"
+#include "lleditmenuhandler.h"
+#include "llspellcheckmenuhandler.h"
+#include "llstyle.h"
+#include "llkeywords.h"
+#include "llpanel.h"
+
+#include <string>
+#include <vector>
+#include <set>
+
+#include <boost/signals2.hpp>
+
+class LLScrollContainer;
+class LLContextMenu;
+class LLUrlMatch;
+
+///
+/// A text segment is used to specify a subsection of a text string
+/// that should be formatted differently, such as a hyperlink. It
+/// includes a start/end offset from the start of the string, a
+/// style to render with, an optional tooltip, etc.
+///
+class LLTextSegment
+: public LLRefCount,
+ public LLMouseHandler
+{
+public:
+ LLTextSegment(S32 start, S32 end)
+ : mStart(start),
+ mEnd(end)
+ {}
+ virtual ~LLTextSegment();
+ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
+
+ virtual bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
+
+ /**
+ * Get number of chars that fit into free part of current line.
+ *
+ * @param num_pixels - maximum width of rect
+ * @param segment_offset - symbol in segment we start processing line from
+ * @param line_offset - symbol in line after which segment starts
+ * @param max_chars - limit of symbols that will fit in current line
+ * @param line_ind - index of not word-wrapped string inside segment for multi-line segments.
+ * Two string separated by word-wrap will have same index.
+ * @return number of chars that will fit into current line
+ */
+ virtual S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
+ virtual void updateLayout(const class LLTextBase& editor);
+ virtual F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
+ virtual bool canEdit() const;
+ virtual void unlinkFromDocument(class LLTextBase* editor);
+ virtual void linkToDocument(class LLTextBase* editor);
+
+ virtual const LLColor4& getColor() const;
+ //virtual void setColor(const LLColor4 &color);
+ virtual LLStyleConstSP getStyle() const;
+ virtual void setStyle(LLStyleConstSP style);
+ virtual void setToken( LLKeywordToken* token );
+ virtual LLKeywordToken* getToken() const;
+ virtual void setToolTip(const std::string& tooltip);
+ virtual void dump() const;
+
+ // LLMouseHandler interface
+ /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleMiddleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleRightMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleDoubleClick(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ bool handleScrollHWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ bool handleToolTip(S32 x, S32 y, MASK mask);
+ /*virtual*/ const std::string& getName() const;
+ /*virtual*/ void onMouseCaptureLost();
+ /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
+ /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
+ /*virtual*/ bool hasMouseCapture();
+
+ S32 getStart() const { return mStart; }
+ void setStart(S32 start) { mStart = start; }
+ S32 getEnd() const { return mEnd; }
+ void setEnd( S32 end ) { mEnd = end; }
+
+protected:
+ S32 mStart;
+ S32 mEnd;
+};
+
+class LLNormalTextSegment : public LLTextSegment
+{
+public:
+ LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor );
+ LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, bool is_visible = true);
+ virtual ~LLNormalTextSegment();
+
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
+ /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
+ /*virtual*/ bool canEdit() const { return true; }
+ /*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); }
+ /*virtual*/ LLStyleConstSP getStyle() const { return mStyle; }
+ /*virtual*/ void setStyle(LLStyleConstSP style) { mStyle = style; }
+ /*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; }
+ /*virtual*/ LLKeywordToken* getToken() const { return mToken; }
+ /*virtual*/ bool getToolTip( std::string& msg ) const;
+ /*virtual*/ void setToolTip(const std::string& tooltip);
+ /*virtual*/ void dump() const;
+
+ /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ bool handleToolTip(S32 x, S32 y, MASK mask);
+
+protected:
+ F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRectf rect);
+
+ virtual const LLWString& getWText() const;
+ virtual const S32 getLength() const;
+
+protected:
+ class LLTextBase& mEditor;
+ LLStyleConstSP mStyle;
+ S32 mFontHeight;
+ LLKeywordToken* mToken;
+ std::string mTooltip;
+ boost::signals2::connection mImageLoadedConnection;
+};
+
+// This text segment is the same as LLNormalTextSegment, the only difference
+// is that LLNormalTextSegment draws value of LLTextBase (LLTextBase::getWText()),
+// but LLLabelTextSegment draws label of the LLTextBase (LLTextBase::mLabel)
+class LLLabelTextSegment : public LLNormalTextSegment
+{
+public:
+ LLLabelTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor );
+ LLLabelTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, bool is_visible = true);
+
+protected:
+
+ /*virtual*/ const LLWString& getWText() const;
+ /*virtual*/ const S32 getLength() const;
+};
+
+// Text segment that represents a single emoji character that has a different style (=font size) than the rest of
+// the document it belongs to
+class LLEmojiTextSegment : public LLNormalTextSegment
+{
+public:
+ LLEmojiTextSegment(LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor);
+ LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end, LLTextBase& editor, bool is_visible = true);
+
+ bool canEdit() const override { return false; }
+ bool handleToolTip(S32 x, S32 y, MASK mask) override;
+};
+
+// Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment)
+class LLOnHoverChangeableTextSegment : public LLNormalTextSegment
+{
+public:
+ LLOnHoverChangeableTextSegment( LLStyleConstSP style, LLStyleConstSP normal_style, S32 start, S32 end, LLTextBase& editor );
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
+ /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask);
+protected:
+ // Style used for text when mouse pointer is over segment
+ LLStyleConstSP mHoveredStyle;
+ // Style used for text when mouse pointer is outside segment
+ LLStyleConstSP mNormalStyle;
+
+};
+
+class LLIndexSegment : public LLTextSegment
+{
+public:
+ LLIndexSegment() : LLTextSegment(0, 0) {}
+};
+
+class LLInlineViewSegment : public LLTextSegment
+{
+public:
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Mandatory<LLView*> view;
+ Optional<bool> force_newline;
+ Optional<S32> left_pad,
+ right_pad,
+ bottom_pad,
+ top_pad;
+ };
+
+ LLInlineViewSegment(const Params& p, S32 start, S32 end);
+ ~LLInlineViewSegment();
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
+ /*virtual*/ void updateLayout(const class LLTextBase& editor);
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
+ /*virtual*/ bool canEdit() const { return false; }
+ /*virtual*/ void unlinkFromDocument(class LLTextBase* editor);
+ /*virtual*/ void linkToDocument(class LLTextBase* editor);
+
+private:
+ S32 mLeftPad;
+ S32 mRightPad;
+ S32 mTopPad;
+ S32 mBottomPad;
+ LLView* mView;
+ bool mForceNewLine;
+};
+
+class LLLineBreakTextSegment : public LLTextSegment
+{
+public:
+
+ LLLineBreakTextSegment(LLStyleConstSP style,S32 pos);
+ LLLineBreakTextSegment(S32 pos);
+ ~LLLineBreakTextSegment();
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
+ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
+
+private:
+ S32 mFontHeight;
+};
+
+class LLImageTextSegment : public LLTextSegment
+{
+public:
+ LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor);
+ ~LLImageTextSegment();
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;
+ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 char_offset, S32 max_chars, S32 line_ind) const;
+ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
+
+ /*virtual*/ bool handleToolTip(S32 x, S32 y, MASK mask);
+ /*virtual*/ void setToolTip(const std::string& tooltip);
+
+private:
+ class LLTextBase& mEditor;
+ LLStyleConstSP mStyle;
+
+protected:
+ std::string mTooltip;
+};
+
+typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
+
+///
+/// The LLTextBase class provides a base class for all text fields, such
+/// as LLTextEditor and LLTextBox. It implements shared functionality
+/// such as Url highlighting and opening.
+///
+class LLTextBase
+: public LLUICtrl,
+ protected LLEditMenuHandler,
+ public LLSpellCheckMenuHandler,
+ public ll::ui::SearchableControl
+{
+public:
+ friend class LLTextSegment;
+ friend class LLNormalTextSegment;
+ friend class LLUICtrlFactory;
+
+ typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t;
+ typedef boost::signals2::signal<bool (const LLUUID& blocked_id, const std::string from)> is_blocked_signal_t;
+
+ struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams>
+ {
+ Alternative<F32> multiple;
+ Alternative<S32> pixels;
+ LineSpacingParams();
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLUIColor> cursor_color,
+ text_color,
+ text_readonly_color,
+ text_tentative_color,
+ bg_readonly_color,
+ bg_writeable_color,
+ bg_focus_color,
+ text_selected_color,
+ bg_selected_color;
+
+ Optional<bool> bg_visible,
+ border_visible,
+ track_end,
+ read_only,
+ skip_link_underline,
+ spellcheck,
+ allow_scroll,
+ plain_text,
+ wrap,
+ use_ellipses,
+ use_emoji,
+ use_color,
+ parse_urls,
+ force_urls_external,
+ parse_highlights,
+ clip,
+ clip_partial,
+ trusted_content,
+ always_show_icons;
+
+ Optional<S32> v_pad,
+ h_pad;
+
+
+ Optional<LineSpacingParams>
+ line_spacing;
+
+ Optional<S32> max_text_length;
+
+ Optional<LLFontGL::ShadowType> font_shadow;
+
+ Optional<LLFontGL::VAlign> text_valign;
+
+ Params();
+ };
+
+ // LLMouseHandler interface
+ /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ bool handleMiddleMouseDown(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ bool handleMiddleMouseUp(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ bool handleRightMouseUp(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ bool handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ bool handleScrollWheel(S32 x, S32 y, S32 clicks) override;
+ /*virtual*/ bool handleToolTip(S32 x, S32 y, MASK mask) override;
+
+ // LLView interface
+ /*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true) override;
+ /*virtual*/ void draw() override;
+
+ // LLUICtrl interface
+ /*virtual*/ bool acceptsTextInput() const override { return !mReadOnly; }
+ /*virtual*/ void setColor(const LLColor4& c) override;
+ virtual void setReadOnlyColor(const LLColor4 &c);
+ /*virtual*/ void onVisibilityChange(bool new_visibility) override;
+
+ /*virtual*/ void setValue(const LLSD& value) override;
+ /*virtual*/ LLTextViewModel* getViewModel() const override;
+
+ // LLEditMenuHandler interface
+ /*virtual*/ bool canDeselect() const override;
+ /*virtual*/ void deselect() override;
+
+ virtual void onFocusReceived() override;
+ virtual void onFocusLost() override;
+
+ void setParseHTML(bool parse_html) { mParseHTML = parse_html; }
+
+ // LLSpellCheckMenuHandler overrides
+ /*virtual*/ bool getSpellCheck() const override;
+
+ /*virtual*/ const std::string& getSuggestion(U32 index) const override;
+ /*virtual*/ U32 getSuggestionCount() const override;
+ /*virtual*/ void replaceWithSuggestion(U32 index) override;
+
+ /*virtual*/ void addToDictionary() override;
+ /*virtual*/ bool canAddToDictionary() const override;
+
+ /*virtual*/ void addToIgnore() override;
+ /*virtual*/ bool canAddToIgnore() const override;
+
+ // Spell checking helper functions
+ std::string getMisspelledWord(U32 pos) const;
+ bool isMisspelledWord(U32 pos) const;
+ void onSpellCheckSettingsChange();
+ virtual void onSpellCheckPerformed(){}
+
+ // used by LLTextSegment layout code
+ bool getWordWrap() const { return mWordWrap; }
+ bool getUseEllipses() const { return mUseEllipses; }
+ bool getUseEmoji() const { return mUseEmoji; }
+ void setUseEmoji(bool value) { mUseEmoji = value; }
+ bool getUseColor() const { return mUseColor; }
+ void setUseColor(bool value) { mUseColor = value; }
+ bool truncate(); // returns true of truncation occurred
+
+ bool isContentTrusted() const { return mTrustedContent; }
+ void setContentTrusted(bool trusted_content) { mTrustedContent = trusted_content; }
+
+ // TODO: move into LLTextSegment?
+ void createUrlContextMenu(S32 x, S32 y, const std::string &url); // create a popup context menu for the given Url
+
+ // Text accessors
+ // TODO: add optional style parameter
+ virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style
+ /*virtual*/ const std::string& getText() const override;
+ void setMaxTextLength(S32 length) { mMaxTextByteLength = length; }
+ S32 getMaxTextLength() { return mMaxTextByteLength; }
+
+ // wide-char versions
+ void setWText(const LLWString& text);
+ const LLWString& getWText() const;
+
+ void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params());
+
+ void setLabel(const LLStringExplicit& label);
+ /*virtual*/ bool setLabelArg(const std::string& key, const LLStringExplicit& text) override;
+
+ const std::string& getLabel() { return mLabel.getString(); }
+ const LLWString& getWlabel() { return mLabel.getWString();}
+
+ void setLastSegmentToolTip(const std::string &tooltip);
+
+ /**
+ * If label is set, draws text label (which is LLLabelTextSegment)
+ * that is visible when no user text provided
+ */
+ void resetLabel();
+
+ void setFont(const LLFontGL* font);
+
+ // force reflow of text
+ void needsReflow(S32 index = 0);
+
+ S32 getLength() const { return getWText().length(); }
+ S32 getLineCount() const { return mLineInfoList.size(); }
+ S32 removeFirstLine(); // returns removed length
+
+ void addDocumentChild(LLView* view);
+ void removeDocumentChild(LLView* view);
+ const LLView* getDocumentView() const { return mDocumentView; }
+ LLRect getVisibleTextRect() const { return mVisibleTextRect; }
+ LLRect getTextBoundingRect();
+ LLRect getVisibleDocumentRect() const;
+
+ S32 getVPad() { return mVPad; }
+ S32 getHPad() { return mHPad; }
+ F32 getLineSpacingMult() { return mLineSpacingMult; }
+ S32 getLineSpacingPixels() { return mLineSpacingPixels; } // only for multiline
+
+ S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, bool round, bool hit_past_end_of_line = true) const;
+ LLRect getLocalRectFromDocIndex(S32 pos) const;
+ LLRect getDocRectFromDocIndex(S32 pos) const;
+
+ void setReadOnly(bool read_only) { mReadOnly = read_only; }
+ bool getReadOnly() { return mReadOnly; }
+
+ void setSkipLinkUnderline(bool skip_link_underline) { mSkipLinkUnderline = skip_link_underline; }
+ bool getSkipLinkUnderline() { return mSkipLinkUnderline; }
+
+ void setParseURLs(bool parse_urls) { mParseHTML = parse_urls; }
+
+ void setPlainText(bool value) { mPlainText = value;}
+ bool getPlainText() const { return mPlainText; }
+
+ // cursor manipulation
+ bool setCursor(S32 row, S32 column);
+ bool setCursorPos(S32 cursor_pos, bool keep_cursor_offset = false);
+ void startOfLine();
+ void endOfLine();
+ void startOfDoc();
+ void endOfDoc();
+ void changePage( S32 delta );
+ void changeLine( S32 delta );
+
+ bool scrolledToStart();
+ bool scrolledToEnd();
+
+ const LLFontGL* getFont() const override { return mFont; }
+
+ virtual void appendLineBreakSegment(const LLStyle::Params& style_params);
+ virtual void appendImageSegment(const LLStyle::Params& style_params);
+ virtual void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
+ boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb);
+ boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);
+ boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb);
+
+ void setWordWrap(bool wrap);
+ LLScrollContainer* getScrollContainer() const { return mScroller; }
+
+protected:
+ // protected member variables
+ // List of offsets and segment index of the start of each line. Always has at least one node (0).
+ struct line_info
+ {
+ line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num);
+ S32 mDocIndexStart;
+ S32 mDocIndexEnd;
+ LLRect mRect;
+ S32 mLineNum; // actual line count (ignoring soft newlines due to word wrap)
+ };
+ typedef std::vector<line_info> line_list_t;
+
+ // helper structs
+ struct compare_bottom
+ {
+ bool operator()(const S32& a, const line_info& b) const;
+ bool operator()(const line_info& a, const S32& b) const;
+ bool operator()(const line_info& a, const line_info& b) const;
+ };
+ struct compare_top
+ {
+ bool operator()(const S32& a, const line_info& b) const;
+ bool operator()(const line_info& a, const S32& b) const;
+ bool operator()(const line_info& a, const line_info& b) const;
+ };
+ struct line_end_compare;
+ typedef std::vector<LLTextSegmentPtr> segment_vec_t;
+
+ // Abstract inner base class representing an undoable editor command.
+ // Concrete sub-classes can be defined for operations such as insert, remove, etc.
+ // Used as arguments to the execute() method below.
+ class TextCmd
+ {
+ public:
+ TextCmd( S32 pos, bool group_with_next, LLTextSegmentPtr segment = LLTextSegmentPtr() )
+ : mPos(pos),
+ mGroupWithNext(group_with_next)
+ {
+ if (segment.notNull())
+ {
+ mSegments.push_back(segment);
+ }
+ }
+ virtual ~TextCmd() {}
+ virtual bool execute(LLTextBase* editor, S32* delta) = 0;
+ virtual S32 undo(LLTextBase* editor) = 0;
+ virtual S32 redo(LLTextBase* editor) = 0;
+ virtual bool canExtend(S32 pos) const { return false; }
+ virtual void blockExtensions() {}
+ virtual bool extendAndExecute( LLTextBase* editor, S32 pos, llwchar c, S32* delta ) { llassert(0); return 0; }
+ virtual bool hasExtCharValue( llwchar value ) const { return false; }
+
+ // Defined here so they can access protected LLTextEditor editing methods
+ S32 insert(LLTextBase* editor, S32 pos, const LLWString &wstr) { return editor->insertStringNoUndo( pos, wstr, &mSegments ); }
+ S32 remove(LLTextBase* editor, S32 pos, S32 length) { return editor->removeStringNoUndo( pos, length ); }
+ S32 overwrite(LLTextBase* editor, S32 pos, llwchar wc) { return editor->overwriteCharNoUndo(pos, wc); }
+
+ S32 getPosition() const { return mPos; }
+ bool groupWithNext() const { return mGroupWithNext; }
+
+ protected:
+ const S32 mPos;
+ bool mGroupWithNext;
+ segment_vec_t mSegments;
+ };
+
+ struct compare_segment_end
+ {
+ bool operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const;
+ };
+ typedef std::multiset<LLTextSegmentPtr, compare_segment_end> segment_set_t;
+
+ // member functions
+ LLTextBase(const Params &p);
+ virtual ~LLTextBase();
+ void initFromParams(const Params& p);
+ virtual void beforeValueChange();
+ virtual void onValueChange(S32 start, S32 end);
+ virtual bool useLabel() const;
+
+ // draw methods
+ virtual void drawSelectionBackground(); // draws the black box behind the selected text
+ void drawCursor();
+ void drawText();
+
+ // modify contents
+ S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted
+ S32 removeStringNoUndo(S32 pos, S32 length);
+ S32 overwriteCharNoUndo(S32 pos, llwchar wc);
+ void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep, bool underline_on_hover_only = false);
+
+
+ // manage segments
+ void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
+ void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp );
+ LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line = true);
+ segment_set_t::iterator getEditableSegIterContaining(S32 index);
+ segment_set_t::const_iterator getEditableSegIterContaining(S32 index) const;
+ segment_set_t::iterator getSegIterContaining(S32 index);
+ segment_set_t::const_iterator getSegIterContaining(S32 index) const;
+ void clearSegments();
+ void createDefaultSegment();
+ virtual void updateSegments();
+ void insertSegment(LLTextSegmentPtr segment_to_insert);
+ const LLStyle::Params& getStyleParams();
+
+ // manage lines
+ S32 getLineStart( S32 line ) const;
+ S32 getLineEnd( S32 line ) const;
+ S32 getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap = true) const;
+ S32 getLineOffsetFromDocIndex( S32 doc_index, bool include_wordwrap = true) const;
+ S32 getFirstVisibleLine() const;
+ std::pair<S32, S32> getVisibleLines(bool fully_visible = false);
+ S32 getLeftOffset(S32 width);
+ void reflow();
+
+ // cursor
+ void updateCursorXPos();
+ void setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool keep_cursor_offset=false );
+ S32 getEditableIndex(S32 index, bool increasing_direction); // constraint cursor to editable segments of document
+ void resetCursorBlink() { mCursorBlinkTimer.reset(); }
+ void updateScrollFromCursor();
+
+ // text selection
+ bool hasSelection() const { return (mSelectionStart !=mSelectionEnd); }
+ void startSelection();
+ void endSelection();
+
+ // misc
+ void updateRects();
+ void needsScroll() { mScrollNeeded = true; }
+
+ struct URLLabelCallback;
+ // Replace a URL with a new icon and label, for example, when
+ // avatar names are looked up.
+ void replaceUrl(const std::string &url, const std::string &label, const std::string& icon);
+
+ void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params());
+ void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);
+ S32 normalizeUri(std::string& uri);
+
+protected:
+ // virtual
+ std::string _getSearchText() const override
+ {
+ return mLabel.getString() + getToolTip();
+ }
+
+ std::vector<LLRect> getSelectionRects();
+
+protected:
+ // text segmentation and flow
+ segment_set_t mSegments;
+ line_list_t mLineInfoList;
+ LLRect mVisibleTextRect; // The rect in which text is drawn. Excludes borders.
+ LLRect mTextBoundingRect;
+
+ // default text style
+ LLStyle::Params mStyle;
+ bool mStyleDirty;
+ const LLFontGL* mFont;
+ const LLFontGL::ShadowType mFontShadow;
+
+ // colors
+ LLUIColor mCursorColor;
+ LLUIColor mFgColor;
+ LLUIColor mReadOnlyFgColor;
+ LLUIColor mTentativeFgColor;
+ LLUIColor mWriteableBgColor;
+ LLUIColor mReadOnlyBgColor;
+ LLUIColor mFocusBgColor;
+ LLUIColor mTextSelectedColor;
+ LLUIColor mSelectedBGColor;
+
+ // cursor
+ S32 mCursorPos; // I-beam is just after the mCursorPos-th character.
+ S32 mDesiredXPixel; // X pixel position where the user wants the cursor to be
+ LLFrameTimer mCursorBlinkTimer; // timer that controls cursor blinking
+
+ // selection
+ S32 mSelectionStart;
+ S32 mSelectionEnd;
+ LLTimer mTripleClickTimer;
+
+ bool mIsSelecting; // Are we in the middle of a drag-select?
+
+ // spell checking
+ bool mSpellCheck;
+ S32 mSpellCheckStart;
+ S32 mSpellCheckEnd;
+ LLTimer mSpellCheckTimer;
+ std::list<std::pair<U32, U32> > mMisspellRanges;
+ std::vector<std::string> mSuggestionList;
+
+ // configuration
+ S32 mHPad; // padding on left of text
+ S32 mVPad; // padding above text
+ LLFontGL::HAlign mHAlign; // horizontal alignment of the document in its entirety
+ LLFontGL::VAlign mVAlign; // vertical alignment of the document in its entirety
+ LLFontGL::VAlign mTextVAlign; // vertical alignment of a text segment within a single line of text
+ F32 mLineSpacingMult; // multiple of line height used as space for a single line of text (e.g. 1.5 to get 50% padding)
+ S32 mLineSpacingPixels; // padding between lines
+ bool mBorderVisible;
+ bool mParseHTML; // make URLs interactive
+ bool mForceUrlsExternal; // URLs from this textbox will be opened in external browser
+ bool mParseHighlights; // highlight user-defined keywords
+ bool mWordWrap;
+ bool mUseEllipses;
+ bool mUseEmoji;
+ bool mUseColor;
+ bool mTrackEnd; // if true, keeps scroll position at end of document during resize
+ bool mReadOnly;
+ bool mBGVisible; // render background?
+ bool mClip; // clip text to widget rect
+ bool mClipPartial; // false if we show lines that are partially inside bounding rect
+ bool mTrustedContent; // if false, does not allow to execute SURL links from this editor
+ bool mPlainText; // didn't use Image or Icon segments
+ bool mAutoIndent;
+ S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
+ bool mSkipTripleClick;
+ bool mAlwaysShowIcons;
+
+ bool mSkipLinkUnderline;
+
+ // support widgets
+ LLHandle<LLContextMenu> mPopupMenuHandle;
+ LLView* mDocumentView;
+ LLScrollContainer* mScroller;
+
+ // transient state
+ S32 mReflowIndex; // index at which to start reflow. S32_MAX indicates no reflow needed.
+ bool mScrollNeeded; // need to change scroll region because of change to cursor position
+ S32 mScrollIndex; // index of first character to keep visible in scroll region
+
+ // Fired when a URL link is clicked
+ commit_signal_t* mURLClickSignal;
+
+ // Used to check if user with given ID is avatar's friend
+ is_friend_signal_t* mIsFriendSignal;
+ is_blocked_signal_t* mIsObjectBlockedSignal;
+
+ LLUIString mLabel; // text label that is visible when no user text provided
+};
+
+#endif
|