diff options
Diffstat (limited to 'indra/llui')
-rw-r--r-- | indra/llui/lldockablefloater.cpp | 10 | ||||
-rw-r--r-- | indra/llui/lldockablefloater.h | 3 | ||||
-rw-r--r-- | indra/llui/lldockcontrol.cpp | 22 | ||||
-rw-r--r-- | indra/llui/llfloater.cpp | 3 | ||||
-rw-r--r-- | indra/llui/llfloater.h | 13 | ||||
-rw-r--r-- | indra/llui/llmenubutton.cpp | 6 | ||||
-rw-r--r-- | indra/llui/llmenubutton.h | 1 | ||||
-rw-r--r-- | indra/llui/llpanel.cpp | 2 | ||||
-rw-r--r-- | indra/llui/llscrolllistctrl.cpp | 2 | ||||
-rw-r--r-- | indra/llui/lltextbase.cpp | 320 | ||||
-rw-r--r-- | indra/llui/lltextbase.h | 4 | ||||
-rw-r--r-- | indra/llui/lltextbox.cpp | 75 | ||||
-rw-r--r-- | indra/llui/lltextbox.h | 1 | ||||
-rw-r--r-- | indra/llui/lltooltip.cpp | 12 | ||||
-rw-r--r-- | indra/llui/lluictrlfactory.h | 2 |
15 files changed, 279 insertions, 197 deletions
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 4525f0a45b..c512ef25be 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -91,6 +91,16 @@ void LLDockableFloater::setVisible(BOOL visible) LLFloater::setVisible(visible); } +void LLDockableFloater::onDockHidden() +{ + setCanDock(FALSE); +} + +void LLDockableFloater::onDockShown() +{ + setCanDock(TRUE); +} + void LLDockableFloater::setDocked(bool docked, bool pop_on_undock) { if (mDockControl.get() != NULL && mDockControl.get()->isDockVisible()) diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index ed90567ad3..7d91d007ee 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -68,6 +68,9 @@ public: */ /*virtual*/ void setVisible(BOOL visible); + virtual void onDockHidden(); + virtual void onDockShown(); + private: /** * Provides unique of dockable floater. diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index 146c7a969a..cdcd823b1c 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -33,6 +33,7 @@ #include "linden_common.h" #include "lldockcontrol.h" +#include "lldockablefloater.h" LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) : @@ -91,8 +92,8 @@ void LLDockControl::repositionDockable() // recalculate dockable position if dock position changed, dock visibility changed, // root view rect changed or recalculation is forced - if (mEnabled && (mPrevDockRect != dockRect || prev_visibility != mDockWidget->getVisible() - || mRootRect != rootRect || mRecalculateDocablePosition)) + if (mPrevDockRect != dockRect || prev_visibility != mDockWidget->getVisible() + || mRootRect != rootRect || mRecalculateDocablePosition) { // undock dockable and off() if dock not visible if (!isDockVisible()) @@ -100,10 +101,25 @@ void LLDockControl::repositionDockable() mDockableFloater->setDocked(false); // force off() since dockable may not have dockControll at this time off(); + LLDockableFloater* dockable_floater = + dynamic_cast<LLDockableFloater*> (mDockableFloater); + if(dockable_floater != NULL) + { + dockable_floater->onDockHidden(); + } } else { - moveDockable(); + if(mEnabled) + { + moveDockable(); + } + LLDockableFloater* dockable_floater = + dynamic_cast<LLDockableFloater*> (mDockableFloater); + if(dockable_floater != NULL) + { + dockable_floater->onDockShown(); + } } mPrevDockRect = dockRect; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 564e4d748f..b7a15a2b33 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -664,7 +664,8 @@ void LLFloater::closeFloater(bool app_quitting) dirtyRect(); - // Close callback + // Close callbacks + onClose(app_quitting); mCloseSignal(this, LLSD(app_quitting)); // Hide or Destroy diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 1dc5177f81..17ffc94014 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -208,8 +208,8 @@ public: virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); virtual void draw(); - // *TODO: Eliminate this in favor of mOpenSignal virtual void onOpen(const LLSD& key) {} + virtual void onClose(bool app_quitting) {} // This cannot be "const" until all derived floater canClose() // methods are const as well. JC @@ -293,11 +293,18 @@ private: void addResizeCtrls(); void addDragHandle(); +public: + // Called when floater is opened, passes mKey + // Public so external views or floaters can watch for this floater opening + commit_signal_t mOpenSignal; + + // Called when floater is closed, passes app_qitting as LLSD() + // Public so external views or floaters can watch for this floater closing + commit_signal_t mCloseSignal; + protected: std::string mRectControl; std::string mVisibilityControl; - commit_signal_t mOpenSignal; // Called when floater is opened, passes mKey - commit_signal_t mCloseSignal; // Called when floater is closed, passes app_qitting as LLSD() LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg LLDragHandle* mDragHandle; diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 2bb6749c83..8dbcd6e229 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -83,6 +83,12 @@ void LLMenuButton::toggleMenu() } +void LLMenuButton::hideMenu() +{ + mMenu->setVisible(FALSE); +} + + BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask ) { if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index 94b0e4355d..02eb9d3806 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -54,6 +54,7 @@ public: /*virtual*/ void draw(); /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask ); + void hideMenu(); protected: friend class LLUICtrlFactory; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 1695aee2b8..69ff3dddc3 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -522,7 +522,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu // be built/added. JC if (parent) { - S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : -1; + S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : parent->getLastTabGroup(); parent->addChild(this, tab_group); } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index af05686c70..7b74b1f93b 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1566,7 +1566,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, MASK mask) LLToolTipMgr::instance().show(LLToolTip::Params() .message(hit_cell->getValue().asString()) .font(LLFontGL::getFontSansSerifSmall()) - .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 4)) + .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 6)) .delay_time(0.2f) .sticky_rect(sticky_rect)); } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 6c048aa908..3dacf979c7 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -209,7 +209,8 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mWordWrap(p.wrap), mUseEllipses( p.use_ellipses ), mParseHTML(p.allow_html), - mParseHighlights(p.parse_highlights) + mParseHighlights(p.parse_highlights), + mHideScrollbar(p.hide_scrollbar) { LLScrollContainer::Params scroll_params; scroll_params.name = "text scroller"; @@ -278,7 +279,9 @@ bool LLTextBase::truncate() // Truncate safely in UTF-8 std::string temp_utf8_text = wstring_to_utf8str(text); temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength ); - getViewModel()->setDisplay(utf8str_to_wstring( temp_utf8_text )); + LLWString text = utf8str_to_wstring( temp_utf8_text ); + // remove extra bit of current string, to preserve formatting, etc. + removeStringNoUndo(text.size(), getWText().size() - text.size()); did_truncate = TRUE; } } @@ -755,47 +758,63 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert) // split old at start point for new segment cur_segmentp->setEnd(segment_to_insert->getStart()); // advance to next segment - ++cur_seg_iter; // insert remainder of old segment LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( cur_segmentp->getStyle(), segment_to_insert->getStart(), old_segment_end, *this); - cur_seg_iter = mSegments.insert(cur_seg_iter, remainder_segment); + mSegments.insert(cur_seg_iter, remainder_segment); remainder_segment->linkToDocument(this); // insert new segment before remainder of old segment - cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert); + mSegments.insert(cur_seg_iter, segment_to_insert); segment_to_insert->linkToDocument(this); - // move to "remanider" segment and start truncation there - ++cur_seg_iter; + // at this point, there will be two overlapping segments owning the text + // associated with the incoming segment } else { - cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert); - ++cur_seg_iter; + mSegments.insert(cur_seg_iter, segment_to_insert); segment_to_insert->linkToDocument(this); } // now delete/truncate remaining segments as necessary + // cur_seg_iter points to segment before incoming segment while(cur_seg_iter != mSegments.end()) { cur_segmentp = *cur_seg_iter; - if (cur_segmentp->getEnd() <= segment_to_insert->getEnd()) + if (cur_segmentp == segment_to_insert) { - cur_segmentp->unlinkFromDocument(this); - segment_set_t::iterator seg_to_erase(cur_seg_iter++); - mSegments.erase(seg_to_erase); + ++cur_seg_iter; + continue; } - else + + if (cur_segmentp->getStart() >= segment_to_insert->getStart()) { - cur_segmentp->setStart(segment_to_insert->getEnd()); - break; + if(cur_segmentp->getEnd() <= segment_to_insert->getEnd()) + { + cur_segmentp->unlinkFromDocument(this); + // grab copy of iterator to erase, and bump it + segment_set_t::iterator seg_to_erase(cur_seg_iter++); + mSegments.erase(seg_to_erase); + continue; + } + else + { + // last overlapping segment, clip to end of incoming segment + // and stop traversal + cur_segmentp->setStart(segment_to_insert->getEnd()); + break; + } } + ++cur_seg_iter; } } + + // layout potentially changed + needsReflow(); } BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleMouseDown(x, y, mask)) { return TRUE; @@ -806,7 +825,7 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleMouseUp(x, y, mask)) { // Did we just click on a link? @@ -824,7 +843,7 @@ BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleMiddleMouseDown(x, y, mask)) { return TRUE; @@ -835,7 +854,7 @@ BOOL LLTextBase::handleMiddleMouseDown(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleMiddleMouseUp(S32 x, S32 y, MASK mask) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleMiddleMouseUp(x, y, mask)) { return TRUE; @@ -846,7 +865,7 @@ BOOL LLTextBase::handleMiddleMouseUp(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleRightMouseDown(S32 x, S32 y, MASK mask) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleRightMouseDown(x, y, mask)) { return TRUE; @@ -857,7 +876,7 @@ BOOL LLTextBase::handleRightMouseDown(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleRightMouseUp(x, y, mask)) { return TRUE; @@ -868,7 +887,7 @@ BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleDoubleClick(x, y, mask)) { return TRUE; @@ -879,7 +898,7 @@ BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleHover(S32 x, S32 y, MASK mask) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleHover(x, y, mask)) { return TRUE; @@ -890,7 +909,7 @@ BOOL LLTextBase::handleHover(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleScrollWheel(S32 x, S32 y, S32 clicks) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleScrollWheel(x, y, clicks)) { return TRUE; @@ -901,7 +920,7 @@ BOOL LLTextBase::handleScrollWheel(S32 x, S32 y, S32 clicks) BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask) { - LLTextSegment* cur_segment = getSegmentAtLocalPos(x, y); + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleToolTip(x, y, mask)) { return TRUE; @@ -1040,109 +1059,106 @@ void LLTextBase::reflow(S32 start_index) S32 cur_top = 0; - if (getLength()) + segment_set_t::iterator seg_iter = mSegments.begin(); + S32 seg_offset = 0; + S32 line_start_index = 0; + const S32 text_width = mTextRect.getWidth(); // optionally reserve room for margin + S32 remaining_pixels = text_width; + LLWString text(getWText()); + S32 line_count = 0; + + // find and erase line info structs starting at start_index and going to end of document + if (!mLineInfoList.empty()) { - segment_set_t::iterator seg_iter = mSegments.begin(); - S32 seg_offset = 0; - S32 line_start_index = 0; - const S32 text_width = mTextRect.getWidth(); // optionally reserve room for margin - S32 remaining_pixels = text_width; - LLWString text(getWText()); - S32 line_count = 0; - - // find and erase line info structs starting at start_index and going to end of document - if (!mLineInfoList.empty()) - { - // find first element whose end comes after start_index - line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare()); - line_start_index = iter->mDocIndexStart; - line_count = iter->mLineNum; - getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset); - mLineInfoList.erase(iter, mLineInfoList.end()); - } + // find first element whose end comes after start_index + line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare()); + line_start_index = iter->mDocIndexStart; + line_count = iter->mLineNum; + getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset); + mLineInfoList.erase(iter, mLineInfoList.end()); + } - S32 line_height = 0; + S32 line_height = 0; - while(seg_iter != mSegments.end()) + while(seg_iter != mSegments.end()) + { + LLTextSegmentPtr segment = *seg_iter; + + // track maximum height of any segment on this line + line_height = llmax(line_height, segment->getMaxHeight()); + S32 cur_index = segment->getStart() + seg_offset; + // find run of text from this segment that we can display on one line + S32 end_index = cur_index; + while(end_index < segment->getEnd() && text[end_index] != '\n') { - LLTextSegmentPtr segment = *seg_iter; - - // track maximum height of any segment on this line - line_height = llmax(line_height, segment->getMaxHeight()); - S32 cur_index = segment->getStart() + seg_offset; - // find run of text from this segment that we can display on one line - S32 end_index = cur_index; - while(end_index < segment->getEnd() && text[end_index] != '\n') - { - ++end_index; - } - - // ask segment how many character fit in remaining space - S32 max_characters = end_index - cur_index; - S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX, - seg_offset, - cur_index - line_start_index, - max_characters); - + ++end_index; + } - S32 segment_width = segment->getWidth(seg_offset, character_count); - remaining_pixels -= segment_width; - S32 text_left = getLeftOffset(text_width - remaining_pixels); + // ask segment how many character fit in remaining space + S32 max_characters = end_index - cur_index; + S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX, + seg_offset, + cur_index - line_start_index, + max_characters); + - seg_offset += character_count; + S32 segment_width = segment->getWidth(seg_offset, character_count); + remaining_pixels -= segment_width; + S32 text_left = getLeftOffset(text_width - remaining_pixels); - S32 last_segment_char_on_line = segment->getStart() + seg_offset; + seg_offset += character_count; - // if we didn't finish the current segment... - if (last_segment_char_on_line < segment->getEnd()) - { - // set up index for next line - // ...skip newline, we don't want to draw - S32 next_line_count = line_count; - if (text[last_segment_char_on_line] == '\n') - { - seg_offset++; - last_segment_char_on_line++; - next_line_count++; - } + S32 last_segment_char_on_line = segment->getStart() + seg_offset; - // add line info and keep going - mLineInfoList.push_back(line_info( - line_start_index, - last_segment_char_on_line, - LLRect(text_left, - cur_top, - text_left + (text_width - remaining_pixels), - cur_top - line_height), - line_count)); - - line_start_index = segment->getStart() + seg_offset; - cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels; - remaining_pixels = text_width; - line_height = 0; - line_count = next_line_count; - } - // ...just consumed last segment.. - else if (++segment_set_t::iterator(seg_iter) == mSegments.end()) - { - mLineInfoList.push_back(line_info( - line_start_index, - last_segment_char_on_line, - LLRect(text_left, - cur_top, - text_left + (text_width - remaining_pixels), - cur_top - line_height), - line_count)); - cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels; - break; - } - // finished a segment and there are segments remaining on this line - else + // if we didn't finish the current segment... + if (last_segment_char_on_line < segment->getEnd()) + { + // set up index for next line + // ...skip newline, we don't want to draw + S32 next_line_count = line_count; + if (text[last_segment_char_on_line] == '\n') { - // subtract pixels used and increment segment - ++seg_iter; - seg_offset = 0; + seg_offset++; + last_segment_char_on_line++; + next_line_count++; } + + // add line info and keep going + mLineInfoList.push_back(line_info( + line_start_index, + last_segment_char_on_line, + LLRect(text_left, + cur_top, + text_left + (text_width - remaining_pixels), + cur_top - line_height), + line_count)); + + line_start_index = segment->getStart() + seg_offset; + cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels; + remaining_pixels = text_width; + line_height = 0; + line_count = next_line_count; + } + // ...just consumed last segment.. + else if (++segment_set_t::iterator(seg_iter) == mSegments.end()) + { + mLineInfoList.push_back(line_info( + line_start_index, + last_segment_char_on_line, + LLRect(text_left, + cur_top, + text_left + (text_width - remaining_pixels), + cur_top - line_height), + line_count)); + cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels; + break; + } + // finished a segment and there are segments remaining on this line + else + { + // subtract pixels used and increment segment + ++seg_iter; + seg_offset = 0; } } @@ -1256,6 +1272,19 @@ S32 LLTextBase::getLineStart( S32 line ) const return mLineInfoList[line].mDocIndexStart; } +S32 LLTextBase::getLineEnd( S32 line ) const +{ + S32 num_lines = getLineCount(); + if (num_lines == 0) + { + return 0; + } + + line = llclamp(line, 0, num_lines-1); + return mLineInfoList[line].mDocIndexEnd; +} + + S32 LLTextBase::getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap) const { @@ -1308,14 +1337,27 @@ S32 LLTextBase::getFirstVisibleLine() const return iter - mLineInfoList.begin(); } -std::pair<S32, S32> LLTextBase::getVisibleLines() const +std::pair<S32, S32> LLTextBase::getVisibleLines(bool fully_visible) { LLRect visible_region = mScroller->getVisibleContentRect(); + line_list_t::const_iterator first_iter; + line_list_t::const_iterator last_iter; - // binary search for line that starts before top of visible buffer and starts before end of visible buffer - line_list_t::const_iterator first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom()); - line_list_t::const_iterator last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_top()); + // make sure we have an up-to-date mLineInfoList + reflow(); + if (fully_visible) + { + // binary search for line that starts before top of visible buffer and starts before end of visible buffer + first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_top()); + last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_bottom()); + } + else + { + // binary search for line that starts before top of visible buffer and starts before end of visible buffer + first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom()); + last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_top()); + } return std::pair<S32, S32>(first_iter - mLineInfoList.begin(), last_iter - mLineInfoList.begin()); } @@ -2147,7 +2189,15 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele S32 start = seg_start; S32 end = llmin( selection_start, seg_end ); S32 length = end - start; - font->render(text, start, rect.mLeft, rect.mTop, color, LLFontGL::LEFT, LLFontGL::TOP, 0, mStyle->getShadowType(), length, rect.getWidth(), &right_x, mEditor.getUseEllipses()); + font->render(text, start, + rect.mLeft, rect.mTop, + color, + LLFontGL::LEFT, LLFontGL::TOP, + 0, + mStyle->getShadowType(), + length, rect.getWidth(), + &right_x, + mEditor.getUseEllipses()); } rect.mLeft = (S32)ceil(right_x); @@ -2158,9 +2208,15 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele S32 end = llmin( selection_end, seg_end ); S32 length = end - start; - font->render(text, start, rect.mLeft, rect.mTop, - LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), - LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, rect.mRight, &right_x, mEditor.getUseEllipses()); + font->render(text, start, + rect.mLeft, rect.mTop, + LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), + LLFontGL::LEFT, LLFontGL::TOP, + 0, + LLFontGL::NO_SHADOW, + length, rect.mRight, + &right_x, + mEditor.getUseEllipses()); } rect.mLeft = (S32)ceil(right_x); if( selection_end < seg_end ) @@ -2169,7 +2225,15 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele S32 start = llmax( selection_end, seg_start ); S32 end = seg_end; S32 length = end - start; - font->render(text, start, rect.mLeft, rect.mTop, color, LLFontGL::LEFT, LLFontGL::TOP, 0, mStyle->getShadowType(), length, rect.mRight, &right_x, mEditor.getUseEllipses()); + font->render(text, start, + rect.mLeft, rect.mTop, + color, + LLFontGL::LEFT, LLFontGL::TOP, + 0, + mStyle->getShadowType(), + length, rect.mRight, + &right_x, + mEditor.getUseEllipses()); } return right_x; } @@ -2263,7 +2327,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart, (F32)num_pixels, max_chars, - mEditor.getWordWrap()); + TRUE); if (num_chars == 0 && line_offset == 0 diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index d0287a99ca..f20134fd6d 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -277,10 +277,11 @@ protected: // 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() const; + std::pair<S32, S32> getVisibleLines(bool fully_visible = false); S32 getLeftOffset(S32 width); void reflow(S32 start_index = 0); @@ -344,6 +345,7 @@ protected: bool mTrackEnd; // if true, keeps scroll position at end of document during resize bool mReadOnly; bool mClip; + bool mHideScrollbar; S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes // support widgets diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 3feca136be..20bceb4675 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -47,26 +47,19 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p) BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; + BOOL handled = LLTextBase::handleMouseDown(x, y, mask); - // HACK: Only do this if there actually is something to click, so that - // overly large text boxes in the older UI won't start eating clicks. - if (isClickable()) + if (getSoundFlags() & MOUSE_DOWN) { - handled = TRUE; + make_ui_sound("UISndClick"); + } + if (!handled && mClickedCallback) + { // Route future Mouse messages here preemptively. (Release on mouse up.) gFocusMgr.setMouseCapture( this ); - - if (getSoundFlags() & MOUSE_DOWN) - { - make_ui_sound("UISndClick"); - } - } - if (!handled) - { - handled = LLTextBase::handleMouseDown(x, y, mask); + handled = TRUE; } return handled; @@ -76,33 +69,30 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - // We only handle the click if the click both started and ended within us - - // HACK: Only do this if there actually is something to click, so that - // overly large text boxes in the older UI won't start eating clicks. - if (isClickable() && hasMouseCapture()) + if (getSoundFlags() & MOUSE_UP) { - handled = TRUE; + make_ui_sound("UISndClickRelease"); + } + // We only handle the click if the click both started and ended within us + if (hasMouseCapture()) + { // Release the mouse gFocusMgr.setMouseCapture( NULL ); - if (getSoundFlags() & MOUSE_UP) - { - make_ui_sound("UISndClickRelease"); - } - - // handle clicks on Urls in the textbox first - handled = LLTextBase::handleMouseUp(x, y, mask); - - // DO THIS AT THE VERY END to allow the button to be destroyed + // DO THIS AT THE VERY END to allow the button to be destroyed // as a result of being clicked. If mouseup in the widget, // it's been clicked if (mClickedCallback && !handled) { mClickedCallback(); + handled = TRUE; } } + else + { + handled = LLTextBase::handleMouseUp(x, y, mask); + } return handled; } @@ -149,30 +139,3 @@ void LLTextBox::onUrlLabelUpdated(const std::string &url, const std::string &lab needsReflow(); } -bool LLTextBox::isClickable() const -{ - // return true if we have been given a click callback - if (mClickedCallback) - { - return true; - } - - // also return true if we have a clickable Url in the text - segment_set_t::const_iterator it; - for (it = mSegments.begin(); it != mSegments.end(); ++it) - { - LLTextSegmentPtr segmentp = *it; - if (segmentp) - { - const LLStyleSP style = segmentp->getStyle(); - if (style && style->isLink()) - { - return true; - } - } - } - - // otherwise there is nothing clickable here - return false; -} - diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index f8c4447b62..da0bcbe972 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -79,7 +79,6 @@ public: protected: void onUrlLabelUpdated(const std::string &url, const std::string &label); - bool isClickable() const; LLUIString mText; callback_t mClickedCallback; diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index d742281f30..c55273cacf 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -38,6 +38,7 @@ // Library includes #include "lltextbox.h" #include "lliconctrl.h" +#include "llmenugl.h" // hideMenus() #include "llui.h" // positionViewNearMouse() #include "llwindow.h" @@ -94,7 +95,16 @@ BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolTipView::handleMouseDown(S32 x, S32 y, MASK mask) { LLToolTipMgr::instance().blockToolTips(); - return LLView::handleMouseDown(x, y, mask); + + if (LLView::handleMouseDown(x, y, mask)) + { + // If we are handling the mouse event menu holder + // won't get a chance to close menus so do this here + LLMenuGL::sMenuContainer->hideMenus(); + return TRUE; + } + + return FALSE; } BOOL LLToolTipView::handleMiddleMouseDown(S32 x, S32 y, MASK mask) diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index e47010c316..3c77c655b8 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -321,7 +321,7 @@ fail: static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block); private: - //static void setCtrlValue(LLView* view, LLXMLNodePtr node); + // this exists to get around dependency on llview static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); // Avoid directly using LLUI and LLDir in the template code |