From 20b46ef6f626c8c7960a4b9c02cae518448497b7 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 31 Jan 2012 15:34:32 -0800
Subject: [PATCH]  EXP-1851 FIX Crash when trying to resize the bottom sections
  more layout logic fixes and added renormalization to fractional sizes to
 eliminate drift

---
 indra/llui/lllayoutstack.cpp                  | 56 +++++++++----------
 indra/llui/lllayoutstack.h                    |  6 +-
 .../xui/en/floater_test_layout_stacks.xml     | 14 ++++-
 3 files changed, 43 insertions(+), 33 deletions(-)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index f43b84794db..88c2218f249 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -129,6 +129,10 @@ void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientatio
 		? getRect().getWidth()
 		: getRect().getHeight()));
 
+	if (mAutoResize == FALSE && mMinDim == -1)
+	{
+		setMinDim(layout_dim);
+	}
 	mTargetDim = llmax(layout_dim, getMinDim());
 }
  
@@ -246,7 +250,7 @@ void LLLayoutStack::removeChild(LLView* view)
 	{
 		mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
 		delete embedded_panelp;
-		updateFractionalSizes();
+		normalizeFractionalSizes();
 		mNeedsLayout = true;
 	}
 
@@ -271,7 +275,7 @@ bool LLLayoutStack::addChild(LLView* child, S32 tab_group)
 	}
 	BOOL result = LLView::addChild(child, tab_group);
 
-	updateFractionalSizes();
+	normalizeFractionalSizes();
 	return result;
 }
 
@@ -306,7 +310,6 @@ void LLLayoutStack::updateLayout()
 
 	bool animation_in_progress = animatePanels();
 	F32 total_visible_fraction = 0.f;
-	F32 total_open_fraction = 0.f;
 	S32 space_to_distribute = (mOrientation == HORIZONTAL)
 							? getRect().getWidth()
 							: getRect().getHeight();
@@ -318,20 +321,17 @@ void LLLayoutStack::updateLayout()
 		if (panelp->mAutoResize)
 		{
 			panelp->mTargetDim = panelp->getRelevantMinDim();
-			if (!panelp->mCollapsed && panelp->getVisible())
-			{
-				total_open_fraction += panelp->mFractionalSize;
-			}
 		}
 		space_to_distribute -= panelp->getVisibleDim() + llround((F32)mPanelSpacing * panelp->getVisibleAmount());
-		total_visible_fraction += panelp->mFractionalSize;
+		total_visible_fraction += panelp->mFractionalSize * panelp->getVisibleAmount();
 	}
 
-	llassert(total_visible_fraction < 1.01f);
+	llassert(total_visible_fraction < 1.05f);
 
 	// don't need spacing after last panel
 	space_to_distribute += panelp ? llround((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0;
 
+	S32 remaining_space = space_to_distribute;
 	F32 fraction_distributed = 0.f;
 	if (space_to_distribute > 0 && total_visible_fraction > 0.f)
 	{	// give space proportionally to visible auto resize panels
@@ -343,26 +343,23 @@ void LLLayoutStack::updateLayout()
 				S32 delta = llround((F32)space_to_distribute * fraction_to_distribute);
 				fraction_distributed += fraction_to_distribute;
 				panelp->mTargetDim += delta;
+				remaining_space -= delta;
 			}
 		}
 	}
 
-	if (fraction_distributed < total_visible_fraction)
-	{	// distribute any left over pixels to non-collapsed, visible panels
-		F32 fraction_left = total_visible_fraction - fraction_distributed;
-		S32 space_left = llround((F32)space_to_distribute * (fraction_left / total_visible_fraction));
+	// distribute any left over pixels to non-collapsed, visible panels
+	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+	{
+		if (remaining_space == 0) break;
 
-		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+		if (panelp->mAutoResize 
+			&& !panelp->mCollapsed 
+			&& panelp->getVisible())
 		{
-			if (panelp->mAutoResize 
-				&& !panelp->mCollapsed 
-				&& panelp->getVisible())
-			{
-				S32 space_for_panel = llmax(0, llround((F32)space_left * (panelp->mFractionalSize / total_open_fraction)));
-				panelp->mTargetDim += space_for_panel;
-				space_left -= space_for_panel;
-				total_open_fraction -= panelp->mFractionalSize;
-			}
+			S32 space_for_panel = remaining_space > 0 ? 1 : -1;
+			panelp->mTargetDim += space_for_panel;
+			remaining_space -= space_for_panel;
 		}
 	}
 
@@ -492,7 +489,7 @@ void LLLayoutStack::updateClass()
 	}
 }
 
-void LLLayoutStack::updateFractionalSizes()
+void LLLayoutStack::normalizeFractionalSizes()
 {
 	F32 total_resizable_dim = 0;
 	S32 num_auto_resize_panels = 0;
@@ -691,7 +688,9 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 		case BEFORE_RESIZED_PANEL:
 			if (panelp->mAutoResize)
 			{	// freeze current size as fraction of overall auto_resize space
-				F32 fractional_adjustment_factor = total_auto_resize_headroom / updated_auto_resize_headroom;
+				F32 fractional_adjustment_factor = updated_auto_resize_headroom == 0.f
+													? 1.f
+													: total_auto_resize_headroom / updated_auto_resize_headroom;
 				F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor,
 													MIN_FRACTIONAL_SIZE,
 													MAX_FRACTIONAL_SIZE);
@@ -720,7 +719,6 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 			else
 			{	// freeze new size as original size
 				panelp->mTargetDim = new_dim;
-				fraction_remaining -= fraction_given_up;
 			}
 			which_panel = NEXT_PANEL;
 			break;
@@ -728,7 +726,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 			if (panelp->mAutoResize)
 			{
 				fraction_remaining -= panelp->mFractionalSize;
-				if (fraction_given_up != 0.f)
+				if (resized_panel->mAutoResize)
 				{
 					panelp->mFractionalSize = llclamp(panelp->mFractionalSize + fraction_given_up, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
 					fraction_given_up = 0.f;
@@ -750,7 +748,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 			which_panel = AFTER_RESIZED_PANEL;
 			break;
 		case AFTER_RESIZED_PANEL:
-			if (panelp->mAutoResize)
+			if (panelp->mAutoResize && fraction_given_up != 0.f)
 			{
 				panelp->mFractionalSize = llclamp(panelp->mFractionalSize + (panelp->mFractionalSize / fraction_remaining) * fraction_given_up,
 												MIN_FRACTIONAL_SIZE,
@@ -760,6 +758,8 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
 			break;
 		}
 	}
+	updateLayout();
+	normalizeFractionalSizes();
 }
 
 void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 6c14a564443..4a8702e318e 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -72,7 +72,7 @@ class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
 	/*virtual*/ void draw();
 	/*virtual*/ void removeChild(LLView*);
 	/*virtual*/ BOOL postBuild();
-	/*virtual*/ bool addChild(LLView* child, S32 tab_group = 0);
+	/*virtual*/ bool addChild(LLView* child, S32 tab_groupdatefractuiona = 0);
 	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
 
 
@@ -111,7 +111,7 @@ class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
 
 	LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;
 	LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const;
-	void updateFractionalSizes();
+	void normalizeFractionalSizes();
 	void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect );
 
 	S32 mPanelSpacing;
@@ -154,7 +154,7 @@ friend class LLUICtrlFactory;
 	void setVisible(BOOL visible);
 
 	S32 getLayoutDim() const;
-	S32 getMinDim() const { return (mMinDim >= 0 || mAutoResize) ? llmax(0, mMinDim) : getLayoutDim(); }
+	S32 getMinDim() const { return llmax(0, mMinDim); }
 	void setMinDim(S32 value) { mMinDim = value; }
 
 	S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : getMinDim(); }
diff --git a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
index f4ef63e73ec..a04050e7eb7 100644
--- a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
@@ -36,6 +36,16 @@
                   background_visible="true">
       <text follows="top|left|right" halign="center" text_color="white">flex</text>
     </layout_panel>
+    <layout_panel name="flex"
+                  auto_resize="true"
+                  user_resize="true"
+                  bg_alpha_color="blue"
+                  height="11"
+                  min_height="0"
+                  visible="true"
+                  background_visible="true">
+      <text follows="top|left|right" halign="center" text_color="white">flex</text>
+    </layout_panel>
     <layout_panel name="flex"
                   auto_resize="true"
                   user_resize="true"
@@ -61,7 +71,7 @@
                   background_visible="true">
       <text follows="top|left|right" halign="center" text_color="white">flex</text>
     </layout_panel>
-    <!--<layout_panel name="flex"
+    <layout_panel name="flex"
                   auto_resize="true"
                   user_resize="true"
                   visible="false"
@@ -69,7 +79,7 @@
                   height="100"
                   background_visible="true">
       <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>-->
+    </layout_panel>
     <layout_panel name="fixed"
                   auto_resize="false"
                   user_resize="true"
-- 
GitLab