diff options
author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 21:25:21 +0200 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2024-05-22 22:40:26 +0300 |
commit | e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch) | |
tree | 1bb897489ce524986f6196201c10ac0d8861aa5f /indra/llui/lltextbase.h | |
parent | 069ea06848f766466f1a281144c82a0f2bd79f3a (diff) |
Fix line endlings
Diffstat (limited to 'indra/llui/lltextbase.h')
-rw-r--r-- | indra/llui/lltextbase.h | 1516 |
1 files changed, 758 insertions, 758 deletions
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index d8e9027bae..f6c7ce6e81 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -1,758 +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_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
+/** + * @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 |