Commits

richard_linden  committed 3551f44

fix for chat history layout bugs
EXT-1728 - there is no new line in the text copied on junction of 2 panels
EXT-1670 - fix chat history use of widgets

reviewed by James

  • Participants
  • Parent commits 9d83200

Comments (0)

Files changed (8)

File indra/llui/llscrollbar.cpp

 	updateThumbRect();
 }
 
-void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb)
+// returns true if document position really changed
+bool LLScrollbar::setDocPos(S32 pos, BOOL update_thumb)
 {
 	pos = llclamp(pos, 0, getDocPosMax());
 	if (pos != mDocPos)
 		{
 			updateThumbRect();
 		}
+		return true;
 	}
+	return false;
 }
 
 void LLScrollbar::setDocSize(S32 size)
 
 BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks)
 {
-	S32 pos = llclamp(mDocPos + clicks * mStepSize, 0, getDocPosMax());
-	if (pos != mDocPos)
-	{
-		setDocPos(pos, TRUE);
-		return TRUE;
-	}
-	return FALSE;
+	BOOL handled = changeLine( clicks * mStepSize, TRUE );
+	return handled;
 }
 
 BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 } // end draw
 
 
-void LLScrollbar::changeLine( S32 delta, BOOL update_thumb )
+bool LLScrollbar::changeLine( S32 delta, BOOL update_thumb )
 {
-	setDocPos(mDocPos + delta, update_thumb);
+	return setDocPos(mDocPos + delta, update_thumb);
 }
 
 void LLScrollbar::setValue(const LLSD& value) 

File indra/llui/llscrollbar.h

 
 	// How many "lines" the "document" has scrolled.
 	// 0 <= DocPos <= DocSize - DocVisibile
-	void				setDocPos( S32 pos, BOOL update_thumb = TRUE );
+	bool				setDocPos( S32 pos, BOOL update_thumb = TRUE );
 	S32					getDocPos() const		{ return mDocPos; }
 
 	BOOL				isAtBeginning();
 
 private:
 	void				updateThumbRect();
-	void				changeLine(S32 delta, BOOL update_thumb );
+	bool				changeLine(S32 delta, BOOL update_thumb );
 
 	callback_t			mChangeCallback;
 

File indra/llui/lltextbase.cpp

 	return pos;
 }
 
-LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
+// returns rectangle of insertion caret 
+// in document coordinate frame from given index into text
+LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const
 {
-	LLRect local_rect;
 	if (mLineInfoList.empty()) 
 	{ 
-		local_rect = mTextRect;
-		local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
-		return local_rect;
+		return LLRect();
 	}
 
+	LLRect doc_rect;
+
 	// clamp pos to valid values
 	pos = llclamp(pos, 0, mLineInfoList.back().mDocIndexEnd - 1);
 
-
 	// find line that contains cursor
 	line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare());
 
-	LLRect scrolled_view_rect = getVisibleDocumentRect();
-	local_rect.mLeft = mTextRect.mLeft - scrolled_view_rect.mLeft + line_iter->mRect.mLeft; 
-	local_rect.mBottom = mTextRect.mBottom + (line_iter->mRect.mBottom - scrolled_view_rect.mBottom);
-	local_rect.mTop = mTextRect.mBottom + (line_iter->mRect.mTop - scrolled_view_rect.mBottom);
+	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;
 			// 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);
-			local_rect.mLeft += segment_width;
+			doc_rect.mLeft += segment_width;
 
 			break;
 		}
 			// 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);
-			local_rect.mLeft += segment_width;
+			doc_rect.mLeft += segment_width;
 			// offset will be 0 for all segments after the first
 			line_seg_offset = 0;
 			// go to next text segment on this line
 		}
 	}
 
-	local_rect.mRight = local_rect.mLeft; 
+	// set rect to 0 width
+	doc_rect.mRight = doc_rect.mLeft; 
+
+	return doc_rect;
+}
+
+LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
+{
+	LLRect local_rect;
+	if (mLineInfoList.empty()) 
+	{ 
+		// return default height rect in upper left
+		local_rect = mTextRect;
+		local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
+		return local_rect;
+	}
+
+	// get the rect in document coordinates
+	LLRect doc_rect = getDocRectFromDocIndex(pos);
+
+	// compensate for scrolled, inset view of doc
+	LLRect scrolled_view_rect = getVisibleDocumentRect();
+	local_rect = doc_rect;
+	local_rect.translate(mTextRect.mLeft - scrolled_view_rect.mLeft, 
+						mTextRect.mBottom - scrolled_view_rect.mBottom);
 
 	return local_rect;
 }
 // LLInlineViewSegment
 //
 
-LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end, bool force_new_line)
+LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end, bool force_new_line, S32 hpad, S32 vpad)
 :	LLTextSegment(start, end),
 	mView(view),
-	mForceNewLine(force_new_line)
+	mForceNewLine(force_new_line),
+	mHPad(hpad), // one sided padding (applied to left and right)
+	mVPad(vpad)
 {
 } 
 
 	}
 	else
 	{
-		width = mView->getRect().getWidth();
-		height = mView->getRect().getHeight();
+		width = mHPad * 2 + mView->getRect().getWidth();
+		height = mVPad * 2 + mView->getRect().getHeight();
 	}
 }
 
 
 void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
 {
-	LLRect start_rect = editor.getLocalRectFromDocIndex(mStart);
-	LLRect doc_rect = editor.getDocumentView()->getRect();
-	mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom);
+	LLRect start_rect = editor.getDocRectFromDocIndex(mStart);
+	mView->setOrigin(start_rect.mLeft + mHPad, start_rect.mBottom + mVPad);
 }
 
 F32	LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
 {
-	return (F32)(draw_rect.mLeft + mView->getRect().getWidth());
+	// return padded width of widget
+	// widget is actually drawn during mDocumentView's draw()
+	return (F32)(draw_rect.mLeft + mView->getRect().getWidth() + mHPad * 2);
 }
 
 void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor)

File indra/llui/lltextbase.h

 
 	S32						getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
 	LLRect					getLocalRectFromDocIndex(S32 pos) const;
+	LLRect					getDocRectFromDocIndex(S32 pos) const;
 
 	void					setReadOnly(bool read_only) { mReadOnly = read_only; }
 	bool					getReadOnly() { return mReadOnly; }
 class LLInlineViewSegment : public LLTextSegment
 {
 public:
-	LLInlineViewSegment(LLView* widget, S32 start, S32 end, bool force_new_line);
+	LLInlineViewSegment(LLView* widget, S32 start, S32 end, bool force_new_line, S32 hpad = 0, S32 vpad = 0);
 	~LLInlineViewSegment();
 	/*virtual*/ void		getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
 	/*virtual*/ S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
 	/*virtual*/ void		linkToDocument(class LLTextBase* editor);
 
 private:
+	S32 mHPad;
+	S32 mVPad;
 	LLView* mView;
 	bool	mForceNewLine;
 };

File indra/llui/lltexteditor.cpp

 	setEnabled( enabled );
 }
 
-void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_new_line)
+void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_new_line, S32 hpad, S32 vpad)
 {
 	// Save old state
 	S32 selection_start = mSelectionStart;
 	// Add carriage return if not first line
 	widget_wide_text = utf8str_to_wstring(widget_text);
 
-	LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size(), force_new_line);
+	LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size(), force_new_line, hpad, vpad);
 	insert(getLength(), widget_wide_text, FALSE, segment);
 
 	needsReflow();

File indra/llui/lltexteditor.h

 	// inserts text at cursor
 	void			insertText(const std::string &text);
 
-	void			appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_newline);
+	void			appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_newline, S32 hpad, S32 vpad);
 	// Non-undoable
 	void			setText(const LLStringExplicit &utf8str);
 

File indra/llui/lluictrlfactory.cpp

 
 LLUICtrlFactory::~LLUICtrlFactory()
 {
-	delete mDummyPanel;
-	mDummyPanel = NULL;
+	// go ahead and leak mDummyPanel since this is static destructor time
+	//delete mDummyPanel;
+	//mDummyPanel = NULL;
 }
 
 void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block)

File indra/newview/llchathistory.cpp

 	if (mLastFromName == from)
 	{
 		view = getSeparator();
-		view_text = "\n";
+		view_text = " ";
 	}
 	else
 	{
 		view = getHeader(avatar_id, from, time);
-		view_text = from + MESSAGE_USERNAME_DATE_SEPARATOR + time;
+		view_text = "\n" + from + MESSAGE_USERNAME_DATE_SEPARATOR + time;
 	}
 	//Prepare the rect for the view
 	LLRect target_rect = getDocumentView()->getRect();
 	view->reshape(target_rect.getWidth(), view->getRect().getHeight());
 	view->setOrigin(target_rect.mLeft, view->getRect().mBottom);
 
-	this->appendWidget(view, view_text, FALSE, TRUE);
+	appendWidget(view, view_text, FALSE, TRUE, mLeftWidgetPad, 0);
 
 	//Append the text message
-	this->appendText(message, TRUE, style_params);
+	appendText(message, TRUE, style_params);
 
 	mLastFromName = from;
-	this->blockUndo();
-	this->setCursorAndScrollToEnd();
+	blockUndo();
+	setCursorAndScrollToEnd();
 }