diff options
| author | Rye <rye@alchemyviewer.org> | 2025-08-20 18:04:55 -0400 | 
|---|---|---|
| committer | Rye <rye@alchemyviewer.org> | 2025-08-20 18:04:55 -0400 | 
| commit | ba30737d8f4add8ddd8c77d18df6497b46583fe9 (patch) | |
| tree | 81e5412a364ff80b5250fe6db9e653d35621c20e /indra/llui/lltexteditor.cpp | |
| parent | f0db568bf8d313a00e10c1c4ee4dd7f716a9d987 (diff) | |
| parent | d5f748c91c650a2ec534c497b9e098ccb317d70b (diff) | |
Merge branch 'develop' of github.com:secondlife/viewer into rye/infinitemac
Diffstat (limited to 'indra/llui/lltexteditor.cpp')
| -rw-r--r-- | indra/llui/lltexteditor.cpp | 112 | 
1 files changed, 108 insertions, 4 deletions
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index fe4cce29ab..58b785fcdd 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -60,6 +60,7 @@  #include "llurlregistry.h"  #include "lltooltip.h"  #include "llmenugl.h" +#include "llchatmentionhelper.h"  #include <queue>  #include "llcombobox.h" @@ -270,9 +271,12 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :      mPrevalidator(p.prevalidator()),      mShowContextMenu(p.show_context_menu),      mShowEmojiHelper(p.show_emoji_helper), +    mShowChatMentionPicker(false),      mEnableTooltipPaste(p.enable_tooltip_paste),      mPassDelete(false), -    mKeepSelectionOnReturn(false) +    mKeepSelectionOnReturn(false), +    mSelectAllOnFocusReceived(false), +    mSelectedOnFocusReceived(false)  {      mSourceID.generate(); @@ -396,6 +400,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, bool case_insen      setCursorPos(loc);      mIsSelecting = true; +    mSelectedOnFocusReceived = false;      mSelectionEnd = mCursorPos;      mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));  } @@ -675,6 +680,13 @@ bool LLTextEditor::canSelectAll() const      return true;  } +//virtual +void LLTextEditor::deselect() +{ +    LLTextBase::deselect(); +    mSelectedOnFocusReceived = false; +} +  // virtual  void LLTextEditor::selectAll()  { @@ -692,6 +704,11 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p      endSelection();  } +void LLTextEditor::setSelectAllOnFocusReceived(bool b) +{ +    mSelectAllOnFocusReceived = b; +} +  void LLTextEditor::insertEmoji(llwchar emoji)  {      LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL; @@ -714,6 +731,30 @@ void LLTextEditor::handleEmojiCommit(llwchar emoji)      }  } +void LLTextEditor::handleMentionCommit(std::string name_url) +{ +    S32 mention_start_pos; +    if (LLChatMentionHelper::instance().isCursorInNameMention(getWText(), mCursorPos, &mention_start_pos)) +    { +        remove(mention_start_pos, mCursorPos - mention_start_pos, true); +        insert(mention_start_pos, utf8str_to_wstring(name_url), false, LLTextSegmentPtr()); + +        std::string new_text(wstring_to_utf8str(getConvertedText())); +        clear(); +        appendTextImpl(new_text, LLStyle::Params(), true); + +        segment_set_t::const_iterator it = getSegIterContaining(mention_start_pos); +        if (it != mSegments.end()) +        { +            setCursorPos((*it)->getEnd() + 1); +        } +        else +        { +            setCursorPos(mention_start_pos); +        } +    } +} +  bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)  {      bool    handled = false; @@ -769,8 +810,16 @@ bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)      // Delay cursor flashing      resetCursorBlink(); +    mSelectedOnFocusReceived = false;      if (handled && !gFocusMgr.getMouseCapture())      { +        if (!mask && mSelectAllOnFocusReceived) +        { +            mIsSelecting = false; +            mSelectionStart = getLength(); +            mSelectionEnd = 0; +            mSelectedOnFocusReceived = true; +        }          gFocusMgr.setMouseCapture( this );      }      return handled; @@ -1103,6 +1152,7 @@ void LLTextEditor::removeCharOrTab()          }          tryToShowEmojiHelper(); +        tryToShowMentionHelper();      }      else      { @@ -1128,6 +1178,7 @@ void LLTextEditor::removeChar()          setCursorPos(mCursorPos - 1);          removeChar(mCursorPos);          tryToShowEmojiHelper(); +        tryToShowMentionHelper();      }      else      { @@ -1189,6 +1240,7 @@ void LLTextEditor::addChar(llwchar wc)      setCursorPos(mCursorPos + addChar( mCursorPos, wc ));      tryToShowEmojiHelper(); +    tryToShowMentionHelper();      if (!mReadOnly && mAutoreplaceCallback != NULL)      { @@ -1247,6 +1299,31 @@ void LLTextEditor::tryToShowEmojiHelper()      }  } +void LLTextEditor::tryToShowMentionHelper() +{ +    if (mReadOnly || !mShowChatMentionPicker) +        return; + +    S32 mention_start_pos; +    LLWString text(getWText()); +    if (LLChatMentionHelper::instance().isCursorInNameMention(text, mCursorPos, &mention_start_pos)) +    { +        const LLRect cursor_rect(getLocalRectFromDocIndex(mention_start_pos)); +        std::string name_part(wstring_to_utf8str(text.substr(mention_start_pos, mCursorPos - mention_start_pos))); +        name_part.erase(0, 1); +        auto cb = [this](std::string name_url) +        { +            handleMentionCommit(name_url); +        }; +        LLChatMentionHelper::instance().showHelper(this, cursor_rect.mLeft, cursor_rect.mTop, name_part, cb); +    } +    else +    { +        LLChatMentionHelper::instance().hideHelper(); +    } +} + +  void LLTextEditor::addLineBreakChar(bool group_together)  {      if( !getEnabled() ) @@ -1873,7 +1950,7 @@ bool LLTextEditor::handleKeyHere(KEY key, MASK mask )      // not handled and let the parent take care of field movement.      if (KEY_TAB == key && mTabsToNextField)      { -        return false; +        return mShowChatMentionPicker && LLChatMentionHelper::instance().handleKey(this, key, mask);      }      if (mReadOnly && mScroller) @@ -1884,9 +1961,13 @@ bool LLTextEditor::handleKeyHere(KEY key, MASK mask )      }      else      { -        if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask)) +        if (!mReadOnly)          { -            return true; +            if ((mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask)) || +                (mShowChatMentionPicker && LLChatMentionHelper::instance().handleKey(this, key, mask))) +            { +                return true; +            }          }          if (mEnableTooltipPaste && @@ -2142,6 +2223,11 @@ void LLTextEditor::focusLostHelper()          gEditMenuHandler = NULL;      } +    if (mSelectedOnFocusReceived) +    { +        deselect(); +    } +      if (mCommitOnFocusLost)      {          onCommit(); @@ -3083,3 +3169,21 @@ S32 LLTextEditor::spacesPerTab()  {      return SPACES_PER_TAB;  } + +LLWString LLTextEditor::getConvertedText() const +{ +    LLWString text = getWText(); +    S32 diff = 0; +    for (auto segment : mSegments) +    { +        if (segment && segment->getStyle() && segment->getStyle()->getDrawHighlightBg()) +        { +            S32 seg_length = segment->getEnd() - segment->getStart(); +            std::string slurl = segment->getStyle()->getLinkHREF(); + +            text.replace(segment->getStart() + diff, seg_length, utf8str_to_wstring(slurl)); +            diff += (S32)slurl.size() - seg_length; +        } +    } +    return text; +}  | 
