diff options
author | Brad Linden <brad@lindenlab.com> | 2022-12-12 17:59:34 -0800 |
---|---|---|
committer | Brad Linden <brad@lindenlab.com> | 2022-12-12 17:59:34 -0800 |
commit | eb526fec0aadcaf30363fdfb1e253a609bf83acc (patch) | |
tree | 6071628f41ca793007b645aa30d255044ddbfe43 /indra/llui | |
parent | c9c611fd12f55ac6d6717ba17139ba61a6db581f (diff) | |
parent | a0c3d69c620a92d73a1008f218680fb4d0ef9255 (diff) |
Merge remote-tracking branch 'origin/main' into DRTVWR-559
Diffstat (limited to 'indra/llui')
-rw-r--r-- | indra/llui/llchat.h | 3 | ||||
-rw-r--r-- | indra/llui/llcheckboxctrl.cpp | 6 | ||||
-rw-r--r-- | indra/llui/llfolderviewmodel.h | 2 | ||||
-rw-r--r-- | indra/llui/llscrolllistctrl.cpp | 39 | ||||
-rw-r--r-- | indra/llui/llscrolllistctrl.h | 2 | ||||
-rw-r--r-- | indra/llui/llspinctrl.cpp | 7 | ||||
-rw-r--r-- | indra/llui/lltextbase.cpp | 197 | ||||
-rw-r--r-- | indra/llui/lltextbase.h | 2 |
8 files changed, 163 insertions, 95 deletions
diff --git a/indra/llui/llchat.h b/indra/llui/llchat.h index c39e44200c..b4fd5f60aa 100644 --- a/indra/llui/llchat.h +++ b/indra/llui/llchat.h @@ -38,7 +38,8 @@ typedef enum e_chat_source_type CHAT_SOURCE_AGENT = 1, CHAT_SOURCE_OBJECT = 2, CHAT_SOURCE_TELEPORT = 3, - CHAT_SOURCE_UNKNOWN = 4 + CHAT_SOURCE_UNKNOWN = 4, + CHAT_SOURCE_REGION = 5, } EChatSourceType; typedef enum e_chat_type diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index 08da599ef2..362fe0c19e 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -203,11 +203,9 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) // it will work fine in case of decrease of space, but if we get more space or text // becomes longer, label will fail to grow so reinit label's dimentions. - static LLUICachedControl<S32> llcheckboxctrl_hpad("UICheckboxctrlHPad", 0); LLRect label_rect = mLabel->getRect(); - S32 new_width = getRect().getWidth() - label_rect.mLeft - llcheckboxctrl_hpad; - label_rect.mRight = label_rect.mLeft + new_width; - mLabel->setRect(label_rect); + S32 new_width = rect.getWidth() - label_rect.mLeft; + mLabel->reshape(new_width, label_rect.getHeight(), TRUE); S32 label_top = label_rect.mTop; mLabel->reshapeToFitText(TRUE); diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 093e213be3..618169a8fe 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -172,7 +172,7 @@ public: virtual BOOL removeItem() = 0; virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; - virtual BOOL isItemCopyable() const = 0; + virtual bool isItemCopyable(bool can_copy_as_link = true) const = 0; virtual BOOL copyToClipboard() const = 0; virtual BOOL cutToClipboard() = 0; virtual bool isCutToClipboard() { return false; }; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 65c7b420ce..88c1bdc0d5 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -3395,3 +3395,42 @@ boost::signals2::connection LLScrollListCtrl::setIsFriendCallback(const is_frien } return mIsFriendSignal->connect(cb); } + +bool LLScrollListCtrl::highlightMatchingItems(const std::string& filter_str) +{ + if (filter_str == "" || filter_str == " ") + { + clearHighlightedItems(); + return false; + } + + bool res = false; + + setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red)); + + std::string filter_str_lc(filter_str); + LLStringUtil::toLower(filter_str_lc); + + std::vector<LLScrollListItem*> data = getAllData(); + std::vector<LLScrollListItem*>::iterator iter = data.begin(); + while (iter != data.end()) + { + LLScrollListCell* cell = (*iter)->getColumn(0); + if (cell) + { + std::string value = cell->getValue().asString(); + LLStringUtil::toLower(value); + if (value.find(filter_str_lc) == std::string::npos) + { + (*iter)->setHighlighted(false); + } + else + { + (*iter)->setHighlighted(true); + res = true; + } + } + iter++; + } + return res; +} diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 77d10fdec7..11ee012185 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -419,6 +419,8 @@ public: void setNeedsSort(bool val = true) { mSorted = !val; } void dirtyColumns(); // some operation has potentially affected column layout or ordering + bool highlightMatchingItems(const std::string& filter_str); + boost::signals2::connection setSortCallback(sort_signal_t::slot_type cb ) { if (!mSortCallback) mSortCallback = new sort_signal_t(); diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index ef7c8ec012..c411aafb1a 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -101,7 +101,10 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) // Spin buttons LLButton::Params up_button_params(p.up_button); up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height); - up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); + // Click callback starts within the button and ends within the button, + // but LLSpinCtrl handles the action continuosly so subsribers needs to + // be informed about click ending even if outside view, use 'up' instead + up_button_params.mouse_up_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); up_button_params.commit_on_capture_lost = true; @@ -110,7 +113,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) LLButton::Params down_button_params(p.down_button); down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height); - down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); + down_button_params.mouse_up_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); down_button_params.commit_on_capture_lost = true; mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7e4aaa53bf..8effd866e0 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -355,95 +355,113 @@ void LLTextBase::onValueChange(S32 start, S32 end) { } - -// Draws the black box behind the selected text -void LLTextBase::drawSelectionBackground() +std::vector<LLRect> LLTextBase::getSelctionRects() { - // Draw selection even if we don't have keyboard focus for search/replace - if( hasSelection() && !mLineInfoList.empty()) - { - std::vector<LLRect> selection_rects; + // Nor supposed to be called without selection + llassert(hasSelection()); + llassert(!mLineInfoList.empty()); - S32 selection_left = llmin( mSelectionStart, mSelectionEnd ); - S32 selection_right = llmax( mSelectionStart, mSelectionEnd ); + std::vector<LLRect> selection_rects; - // Skip through the lines we aren't drawing. - LLRect content_display_rect = getVisibleDocumentRect(); + S32 selection_left = llmin(mSelectionStart, mSelectionEnd); + S32 selection_right = llmax(mSelectionStart, mSelectionEnd); - // binary search for line that starts before top of visible buffer - line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom()); - line_list_t::const_iterator end_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top()); + // Skip through the lines we aren't drawing. + LLRect content_display_rect = getVisibleDocumentRect(); - bool done = false; + // binary search for line that starts before top of visible buffer + line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom()); + line_list_t::const_iterator end_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top()); - // Find the coordinates of the selected area - for (;line_iter != end_iter && !done; ++line_iter) - { - // is selection visible on this line? - if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right) - { - segment_set_t::iterator segment_iter; - S32 segment_offset; - getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset); - - LLRect selection_rect; - selection_rect.mLeft = line_iter->mRect.mLeft; - selection_rect.mRight = line_iter->mRect.mLeft; - selection_rect.mBottom = line_iter->mRect.mBottom; - selection_rect.mTop = line_iter->mRect.mTop; - - for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0) - { - LLTextSegmentPtr segmentp = *segment_iter; + bool done = false; - S32 segment_line_start = segmentp->getStart() + segment_offset; - S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd); + // Find the coordinates of the selected area + for (; line_iter != end_iter && !done; ++line_iter) + { + // is selection visible on this line? + if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right) + { + segment_set_t::iterator segment_iter; + S32 segment_offset; + getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset); - if (segment_line_start > segment_line_end) break; + // Use F32 otherwise a string of multiple segments + // will accumulate a large error + F32 left_precise = line_iter->mRect.mLeft; + F32 right_precise = line_iter->mRect.mLeft; - S32 segment_width = 0; - S32 segment_height = 0; + for (; segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0) + { + LLTextSegmentPtr segmentp = *segment_iter; - // if selection after beginning of segment - if(selection_left >= segment_line_start) - { - S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start; - segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); - selection_rect.mLeft += segment_width; - } + S32 segment_line_start = segmentp->getStart() + segment_offset; + S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd); - // if selection_right == segment_line_end then that means we are the first character of the next segment - // or first character of the next line, in either case we want to add the length of the current segment - // to the selection rectangle and continue. - // if selection right > segment_line_end then selection spans end of current segment... - if (selection_right >= segment_line_end) - { - // extend selection slightly beyond end of line - // to indicate selection of newline character (use "n" character to determine width) - S32 num_chars = segment_line_end - segment_line_start; - segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); - selection_rect.mRight += segment_width; - } - // else if selection ends on current segment... - else - { - S32 num_chars = selection_right - segment_line_start; - segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); - selection_rect.mRight += segment_width; + if (segment_line_start > segment_line_end) break; - break; - } - } - selection_rects.push_back(selection_rect); - } - } + F32 segment_width = 0; + S32 segment_height = 0; + + // if selection after beginning of segment + if (selection_left >= segment_line_start) + { + S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start; + segmentp->getDimensionsF32(segment_offset, num_chars, segment_width, segment_height); + left_precise += segment_width; + } + + // if selection_right == segment_line_end then that means we are the first character of the next segment + // or first character of the next line, in either case we want to add the length of the current segment + // to the selection rectangle and continue. + // if selection right > segment_line_end then selection spans end of current segment... + if (selection_right >= segment_line_end) + { + // extend selection slightly beyond end of line + // to indicate selection of newline character (use "n" character to determine width) + S32 num_chars = segment_line_end - segment_line_start; + segmentp->getDimensionsF32(segment_offset, num_chars, segment_width, segment_height); + right_precise += segment_width; + } + // else if selection ends on current segment... + else + { + S32 num_chars = selection_right - segment_line_start; + segmentp->getDimensionsF32(segment_offset, num_chars, segment_width, segment_height); + right_precise += segment_width; + + break; + } + } + + LLRect selection_rect; + selection_rect.mLeft = left_precise; + selection_rect.mRight = right_precise; + selection_rect.mBottom = line_iter->mRect.mBottom; + selection_rect.mTop = line_iter->mRect.mTop; + + selection_rects.push_back(selection_rect); + } + } + + return selection_rects; +} + +// Draws the black box behind the selected text +void LLTextBase::drawSelectionBackground() +{ + // Draw selection even if we don't have keyboard focus for search/replace + if (hasSelection() && !mLineInfoList.empty()) + { + std::vector<LLRect> selection_rects = getSelctionRects(); // Draw the selection box (we're using a box instead of reversing the colors on the selected text). gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); const LLColor4& color = mSelectedBGColor; F32 alpha = hasFocus() ? 0.7f : 0.3f; alpha *= getDrawContext().mAlpha; + LLColor4 selection_color(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], alpha); + LLRect content_display_rect = getVisibleDocumentRect(); for (std::vector<LLRect>::iterator rect_it = selection_rects.begin(); rect_it != selection_rects.end(); @@ -2551,7 +2569,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, } S32 pos = getLength(); - S32 start_x = line_iter->mRect.mLeft + doc_rect.mLeft; + F32 start_x = line_iter->mRect.mLeft + doc_rect.mLeft; segment_set_t::iterator line_seg_iter; S32 line_seg_offset; @@ -2563,8 +2581,9 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, S32 segment_line_start = segmentp->getStart() + line_seg_offset; S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd) - segment_line_start; - S32 text_width, text_height; - bool newline = segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height); + F32 text_width; + S32 text_height; + bool newline = segmentp->getDimensionsF32(line_seg_offset, segment_line_length, text_width, text_height); if(newline) { @@ -2584,8 +2603,9 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, S32 offset; if (!segmentp->canEdit()) { - S32 segment_width, segment_height; - segmentp->getDimensions(0, segmentp->getEnd() - segmentp->getStart(), segment_width, segment_height); + F32 segment_width; + S32 segment_height; + segmentp->getDimensionsF32(0, segmentp->getEnd() - segmentp->getStart(), segment_width, segment_height); if (round && local_x - start_x > segment_width / 2) { offset = segment_line_length; @@ -2632,17 +2652,11 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const return LLRect(); } - LLRect doc_rect; - // clamp pos to valid values pos = llclamp(pos, 0, mLineInfoList.back().mDocIndexEnd - 1); line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare()); - doc_rect.mLeft = line_iter->mRect.mLeft; - doc_rect.mBottom = line_iter->mRect.mBottom; - doc_rect.mTop = line_iter->mRect.mTop; - segment_set_t::iterator line_seg_iter; S32 line_seg_offset; segment_set_t::iterator cursor_seg_iter; @@ -2650,6 +2664,8 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset); getSegmentAndOffset(pos, &cursor_seg_iter, &cursor_seg_offset); + F32 doc_left_precise = line_iter->mRect.mLeft; + while(line_seg_iter != mSegments.end()) { const LLTextSegmentPtr segmentp = *line_seg_iter; @@ -2657,18 +2673,20 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const if (line_seg_iter == cursor_seg_iter) { // cursor advanced to right based on difference in offset of cursor to start of line - S32 segment_width, segment_height; - segmentp->getDimensions(line_seg_offset, cursor_seg_offset - line_seg_offset, segment_width, segment_height); - doc_rect.mLeft += segment_width; + F32 segment_width; + S32 segment_height; + segmentp->getDimensionsF32(line_seg_offset, cursor_seg_offset - line_seg_offset, segment_width, segment_height); + doc_left_precise += segment_width; break; } else { // add remainder of current text segment to cursor position - S32 segment_width, segment_height; - segmentp->getDimensions(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset, segment_width, segment_height); - doc_rect.mLeft += segment_width; + F32 segment_width; + S32 segment_height; + segmentp->getDimensionsF32(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset, segment_width, segment_height); + doc_left_precise += segment_width; // offset will be 0 for all segments after the first line_seg_offset = 0; // go to next text segment on this line @@ -2676,6 +2694,11 @@ LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const } } + LLRect doc_rect; + doc_rect.mLeft = doc_left_precise; + doc_rect.mBottom = line_iter->mRect.mBottom; + doc_rect.mTop = line_iter->mRect.mTop; + // set rect to 0 width doc_rect.mRight = doc_rect.mLeft; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 25f8fa1c2b..e3cf56a5ee 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -638,6 +638,8 @@ protected: return mLabel.getString() + getToolTip(); } + std::vector<LLRect> getSelctionRects(); + protected: // text segmentation and flow segment_set_t mSegments; |