diff options
| author | Seth ProductEngine <slitovchuk@productengine.com> | 2011-04-10 00:31:52 +0300 | 
|---|---|---|
| committer | Seth ProductEngine <slitovchuk@productengine.com> | 2011-04-10 00:31:52 +0300 | 
| commit | c94d6875396f1d68be5fddb93718543e4548a131 (patch) | |
| tree | a1bba1530826a51680ef3e86dec2872aa7d4d9e5 /indra | |
| parent | 07a122c43c0b3d01af7497daff3d27251d839792 (diff) | |
STORM-721 FIXED Fix for text clipping in a textbox without a scroller.
Committed on behalf of Richard Linden:
This patch makes clipping work consistently with text and embedded widgets. The widgets will only be displayed if the corresponding text they are embedded in is displayed.  There is also a new param "clip" for text widgets that can be used to disable clipping entirely.  I introduced this as a potential work around due to the fact that we *used* to assume that text was never clipped in the vertical direction unless we had scrolling turned on.  This hasn't been the case for over a year, but now we can selectively turn off vertical text clipping with (clip="false") if we have to.
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llui/lltextbase.cpp | 103 | ||||
| -rw-r--r-- | indra/llui/lltextbase.h | 4 | 
2 files changed, 80 insertions, 27 deletions
| diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 49537ef78f..82269282ef 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -157,6 +157,7 @@ LLTextBase::Params::Params()  	read_only("read_only", false),  	v_pad("v_pad", 0),  	h_pad("h_pad", 0), +	clip("clip", true),  	clip_partial("clip_partial", true),  	line_spacing("line_spacing"),  	max_text_length("max_length", 255), @@ -199,6 +200,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  	mVAlign(p.font_valign),  	mLineSpacingMult(p.line_spacing.multiple),  	mLineSpacingPixels(p.line_spacing.pixels), +	mClip(p.clip),  	mClipPartial(p.clip_partial && !p.allow_scroll),  	mTrackEnd( p.track_end ),  	mScrollIndex(-1), @@ -334,7 +336,7 @@ void LLTextBase::drawSelectionBackground()  		// 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::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top()); +		line_list_t::const_iterator end_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top());  		bool done = false; @@ -512,7 +514,6 @@ void LLTextBase::drawText()  		selection_right = llmax( mSelectionStart, mSelectionEnd );  	} -	LLRect scrolled_view_rect = getVisibleDocumentRect();  	std::pair<S32, S32> line_range = getVisibleLines(mClipPartial);  	S32 first_line = line_range.first;  	S32 last_line = line_range.second; @@ -545,10 +546,10 @@ void LLTextBase::drawText()  			line_end = next_start;  		} -		LLRect text_rect(line.mRect.mLeft + mVisibleTextRect.mLeft - scrolled_view_rect.mLeft, -						line.mRect.mTop - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom, -						llmin(mDocumentView->getRect().getWidth(), line.mRect.mRight) - scrolled_view_rect.mLeft, -						line.mRect.mBottom - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom); +		LLRect text_rect(line.mRect); +		text_rect.mRight = llmin(mDocumentView->getRect().getWidth(), text_rect.mRight); // clamp right edge to document extents +		text_rect.translate(mVisibleTextRect.mLeft, mVisibleTextRect.mBottom); // translate into display region of text widget +		text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position  		// draw a single line of text  		S32 seg_start = line_start; @@ -993,14 +994,28 @@ void LLTextBase::draw()  		updateScrollFromCursor();  	} -	LLRect doc_rect; +	LLRect text_rect;  	if (mScroller)  	{ -		mScroller->localRectToOtherView(mScroller->getContentWindowRect(), &doc_rect, this); +		mScroller->localRectToOtherView(mScroller->getContentWindowRect(), &text_rect, this);  	}  	else  	{ -		doc_rect = getLocalRect(); +		LLRect visible_lines_rect; +		std::pair<S32, S32> line_range = getVisibleLines(mClipPartial); +		for (S32 i = line_range.first; i < line_range.second; i++) +		{ +			if (visible_lines_rect.isEmpty()) +			{ +				visible_lines_rect = mLineInfoList[i].mRect; +			} +			else +			{ +				visible_lines_rect.unionWith(mLineInfoList[i].mRect); +			} +		} +		text_rect = visible_lines_rect; +		text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom);  	}  	if (mBGVisible) @@ -1010,28 +1025,37 @@ void LLTextBase::draw()  		LLRect bg_rect = mVisibleTextRect;  		if (mScroller)  		{ -			bg_rect.intersectWith(doc_rect); +			bg_rect.intersectWith(text_rect);  		}  		LLColor4 bg_color = mReadOnly   							? mReadOnlyBgColor.get()  							: hasFocus()   								? mFocusBgColor.get()   								: mWriteableBgColor.get(); -		gl_rect_2d(doc_rect, bg_color % alpha, TRUE); +		gl_rect_2d(text_rect, bg_color % alpha, TRUE);  	} -	// draw document view -	LLUICtrl::draw(); - -	{ -		// only clip if we support scrolling... -		// since convention is that text boxes never vertically truncate their contents -		// regardless of rect bounds -		LLLocalClipRect clip(doc_rect, mScroller != NULL); + 	bool should_clip = mClip || mScroller != NULL; + 	{ LLLocalClipRect clip(text_rect, should_clip); +  + 		// draw document view + 		if (mScroller) +		{ + 			drawChild(mScroller); + 		} + 		else + 		{ + 			drawChild(mDocumentView); + 		} +   		drawSelectionBackground();  		drawText();  		drawCursor();  	} +  + 	mDocumentView->setVisible(FALSE); + 	LLUICtrl::draw(); + 	mDocumentView->setVisible(TRUE);  } @@ -1415,7 +1439,7 @@ S32	LLTextBase::getFirstVisibleLine() const  	return iter - mLineInfoList.begin();  } -std::pair<S32, S32>	LLTextBase::getVisibleLines(bool fully_visible)  +std::pair<S32, S32>	LLTextBase::getVisibleLines(bool require_fully_visible)   {  	LLRect visible_region = getVisibleDocumentRect();  	line_list_t::const_iterator first_iter; @@ -1424,14 +1448,14 @@ std::pair<S32, S32>	LLTextBase::getVisibleLines(bool fully_visible)  	// make sure we have an up-to-date mLineInfoList  	reflow(); -	if (fully_visible) +	if (require_fully_visible)  	{  		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()); +		last_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_bottom());  	}  	else  	{ -		first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom()); +		first_iter = std::upper_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()); @@ -2405,14 +2429,41 @@ LLRect LLTextBase::getVisibleDocumentRect() const  	{  		return mScroller->getVisibleContentRect();  	} -	else +	else if (mClip)  	{ -		// entire document rect is visible when not scrolling +		LLRect visible_text_rect = getVisibleTextRect(); +		LLRect doc_rect = mDocumentView->getRect(); +		visible_text_rect.translate(-doc_rect.mLeft, -doc_rect.mBottom); + +		// reject partially visible lines +		LLRect visible_lines_rect; +		for (line_list_t::const_iterator it = mLineInfoList.begin(), end_it = mLineInfoList.end(); +			it != end_it; +			++it) +		{ +			bool line_visible = mClipPartial ? visible_text_rect.contains(it->mRect) : visible_text_rect.overlaps(it->mRect); +			if (line_visible) +			{ +				if (visible_lines_rect.isEmpty()) +				{ +					visible_lines_rect = it->mRect; +				} +				else +				{ +					visible_lines_rect.unionWith(it->mRect); +				} +			} +		} +		return visible_lines_rect; +	} +	else +	{	// entire document rect is visible  		// but offset according to height of widget +	  		LLRect doc_rect = mDocumentView->getLocalRect();  		doc_rect.mLeft -= mDocumentView->getRect().mLeft;  		// adjust for height of text above widget baseline -		doc_rect.mBottom = doc_rect.getHeight() - mVisibleTextRect.getHeight(); +		doc_rect.mBottom = llmin(0, doc_rect.getHeight() - mVisibleTextRect.getHeight());  		return doc_rect;  	}  } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index aafcf8ceb0..7d545a1ba6 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -265,6 +265,7 @@ public:  								use_ellipses,  								parse_urls,  								parse_highlights, +								clip,  								clip_partial;  		Optional<S32>			v_pad, @@ -338,7 +339,7 @@ public:  	void					addDocumentChild(LLView* view);  	void					removeDocumentChild(LLView* view);  	const LLView*			getDocumentView() const { return mDocumentView; } -	LLRect					getVisibleTextRect() { return mVisibleTextRect; } +	LLRect					getVisibleTextRect() const { return mVisibleTextRect; }  	LLRect					getTextBoundingRect();  	LLRect					getVisibleDocumentRect() const; @@ -552,6 +553,7 @@ protected:  	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						mPlainText;			// didn't use Image or Icon segments  	S32							mMaxTextByteLength;	// Maximum length mText is allowed to be in bytes | 
