From 8576eaa3bf011bec4f7b64c82f962c26e067c52f Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 6 May 2020 23:52:38 +0300
Subject: [PATCH] SL-13119 Fixed label updates

---
 indra/llui/llfolderviewitem.cpp      | 57 ++++++++++++++++++++++------
 indra/llui/llfolderviewitem.h        | 10 +++--
 indra/newview/llconversationview.cpp |  8 ----
 3 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 863a72b6c03..1c6c7b1b358 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -122,7 +122,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
 :	LLView(p),
 	mLabelWidth(0),
 	mLabelWidthDirty(false),
-    mLabelNeedsRefresh(false),
+    mSuffixNeedsRefresh(false),
     mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT),
 	mParentFolder( NULL ),
 	mIsSelected( FALSE ),
@@ -183,14 +183,20 @@ LLFolderViewItem::~LLFolderViewItem()
 BOOL LLFolderViewItem::postBuild()
 {
     LLFolderViewModelItem& vmi = *getViewModelItem();
-    // getDisplayName() is slightly expensive and requires a filter reset
+    // getDisplayName() is expensive (due to internal getLabelSuffix() and name building)
+    // it also sets search strings so it requires a filter reset
     mLabel = vmi.getDisplayName();
     setToolTip(vmi.getName());
 
     // Dirty the filter flag of the model from the view (CHUI-849)
     vmi.dirtyFilter();
 
-    mLabelNeedsRefresh = true;
+    // Don't do full refresh on constructor if it is possible to avoid
+    // it significantly slows down bulk view creation.
+    // Todo: Ideally we need to move getDisplayName() out of constructor as well.
+    // Like: make a logic that will let filter update search string,
+    // while LLFolderViewItem::arrange() updates visual part
+    mSuffixNeedsRefresh = true;
     mLabelWidthDirty = true;
 	return TRUE;
 }
@@ -289,24 +295,51 @@ BOOL LLFolderViewItem::isPotentiallyVisible(S32 filter_generation)
 
 void LLFolderViewItem::refresh()
 {
-	LLFolderViewModelItem& vmi = *getViewModelItem();
+    LLFolderViewModelItem& vmi = *getViewModelItem();
+
+    mLabel = vmi.getDisplayName();
+    setToolTip(vmi.getName());
+    // icons are slightly expensive to get, can be optimized
+    // see LLInventoryIcon::getIcon()
+    mIcon = vmi.getIcon();
+    mIconOpen = vmi.getIconOpen();
+    mIconOverlay = vmi.getIconOverlay();
+
+    if (mRoot->useLabelSuffix())
+    {
+        // Very Expensive!
+        // Can do a number of expensive checks, like checking active motions, wearables or friend list
+        mLabelStyle = vmi.getLabelStyle();
+        mLabelSuffix = vmi.getLabelSuffix();
+    }
+
+    // Dirty the filter flag of the model from the view (CHUI-849)
+    vmi.dirtyFilter();
+
+    mLabelWidthDirty = true;
+    mSuffixNeedsRefresh = false;
+}
+
+void LLFolderViewItem::refreshSuffix()
+{
+	LLFolderViewModelItem const* vmi = getViewModelItem();
 
     // icons are slightly expensive to get, can be optimized
     // see LLInventoryIcon::getIcon()
-	mIcon = vmi.getIcon();
-	mIconOpen = vmi.getIconOpen();
-	mIconOverlay = vmi.getIconOverlay();
+	mIcon = vmi->getIcon();
+    mIconOpen = vmi->getIconOpen();
+    mIconOverlay = vmi->getIconOverlay();
 
 	if (mRoot->useLabelSuffix())
 	{
         // Very Expensive!
         // Can do a number of expensive checks, like checking active motions, wearables or friend list
-		mLabelStyle = vmi.getLabelStyle();
-		mLabelSuffix = vmi.getLabelSuffix();
+        mLabelStyle = vmi->getLabelStyle();
+        mLabelSuffix = vmi->getLabelSuffix();
 	}
 
     mLabelWidthDirty = true;
-    mLabelNeedsRefresh = false;
+    mSuffixNeedsRefresh = false;
 }
 
 // Utility function for LLFolderView
@@ -357,11 +390,11 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height )
 		: 0;
 	if (mLabelWidthDirty)
 	{
-        if (mLabelNeedsRefresh)
+        if (mSuffixNeedsRefresh)
         {
             // Expensive. But despite refreshing label,
             // it is purely visual, so it is fine to do at our laisure
-            refresh();
+            refreshSuffix();
         }
 		mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; 
 		mLabelWidthDirty = false;
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index 8693e1e0f93..da09d139e98 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -90,12 +90,12 @@ class LLFolderViewItem : public LLView
 	std::string					mLabel;
 	S32							mLabelWidth;
 	bool						mLabelWidthDirty;
-	bool						mLabelNeedsRefresh;
     S32                         mLabelPaddingRight;
 	LLFolderViewFolder*			mParentFolder;
 	LLPointer<LLFolderViewModelItem> mViewModelItem;
 	LLFontGL::StyleFlags		mLabelStyle;
 	std::string					mLabelSuffix;
+	bool						mSuffixNeedsRefresh; //suffix and icons
 	LLUIImagePtr				mIcon,
 								mIconOpen,
 								mIconOverlay;
@@ -268,8 +268,12 @@ class LLFolderViewItem : public LLView
 	virtual BOOL	isPotentiallyVisible(S32 filter_generation = -1);
 
     // refresh information from the object being viewed.
-    // refreshes sufixes and sets icons. Expensive!
-	virtual void refresh();
+    // refreshes label, suffixes and sets icons. Expensive!
+    // Causes filter update
+    virtual void refresh();
+    // refreshes suffixes and sets icons. Expensive!
+    // Does not need filter update
+	virtual void refreshSuffix();
 
 	// LLView functionality
 	virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index fda52670418..093e772abec 100644
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -431,10 +431,6 @@ void LLConversationViewSession::refresh()
 	LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem());
 	vmi->resetRefresh();
 
-    mLabel = vmi->getDisplayName(); // needs a filter reset
-    setToolTip(vmi->getName());
-    vmi->dirtyFilter();
-
 	if (mSessionTitle)
 	{
 		mSessionTitle->setText(vmi->getDisplayName());
@@ -626,10 +622,6 @@ void LLConversationViewParticipant::refresh()
 	// *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat
 	mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted());
 
-    mLabel = participant_model->getDisplayName(); // needs a filter reset
-    setToolTip(participant_model->getName());
-    participant_model->dirtyFilter();
-
 	// Do the regular upstream refresh
 	LLFolderViewItem::refresh();
 }
-- 
GitLab