From 812d18515ddefd11fe8c5fc7f655280a231670f5 Mon Sep 17 00:00:00 2001
From: Mike Antipov <mantipov@productengine.com>
Date: Tue, 17 Nov 2009 13:03:08 +0200
Subject: [PATCH] Completed major sub-task EXT-991 (Update bottom bar behavior
 on resize)  - added possibility to shrink/extend buttons (gestures, move,
 view) while resizing  - I had to add LLLayoutStack::getPanelMinSize interface
 to validate width of Layout panels with these buttons

--HG--
branch : product-engine
---
 indra/llui/lllayoutstack.cpp                  |  13 ++
 indra/llui/lllayoutstack.h                    |   8 ++
 indra/newview/llbottomtray.cpp                | 131 +++++++++++++++++-
 indra/newview/llbottomtray.h                  |  22 ++-
 .../skins/default/xui/en/panel_bottomtray.xml |  14 +-
 5 files changed, 178 insertions(+), 10 deletions(-)

diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 14a6ddb7e0e..1fb618adeee 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -413,6 +413,19 @@ void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL au
 	}
 }
 
+bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp)
+{
+	LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+
+	if (panel)
+	{
+		if (min_widthp) *min_widthp = panel->mMinWidth;
+		if (min_heightp) *min_heightp = panel->mMinHeight;
+	}
+
+	return NULL != panel;
+}
+
 static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks");
 void LLLayoutStack::updateLayout(BOOL force_resize)
 {
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 9cbcb285dca..abd5436018d 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -82,6 +82,14 @@ class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
 
 	void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize);
 	
+	/**
+	 * Gets minimal width and/or height of the specified by name panel.
+	 *
+	 * If it is necessary to get only the one dimension pass NULL for another one.
+	 * @returns true if specified by panel_name internal panel exists, false otherwise.
+	 */
+	bool getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp);
+	
 	void updateLayout(BOOL force_resize = FALSE);
 	static void updateClass();
 
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 958dbf226a8..3c34aa4fa48 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -317,6 +317,10 @@ BOOL LLBottomTray::postBuild()
 	// Registering Chat Bar to receive Voice client status change notifications.
 	gVoiceClient->addObserver(this);
 
+	mObjectDefaultWidthMap[RS_BUTTON_GESTURES] = mGesturePanel->getRect().getWidth();
+	mObjectDefaultWidthMap[RS_BUTTON_MOVEMENT] = mMovementPanel->getRect().getWidth();
+	mObjectDefaultWidthMap[RS_BUTTON_CAMERA]   = mCamPanel->getRect().getWidth();
+
 	return TRUE;
 }
 
@@ -402,7 +406,6 @@ void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent)
 		}
 	}
 
-	lldebugs << "There is no enough width to reshape all children: " << extra_shrink_width << llendl;
 	if (should_be_reshaped)
 	{
 		lldebugs << "Reshape all children with width: " << width << llendl;
@@ -473,7 +476,12 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width)
 	S32 buttons_freed_width = 0;
 	if (still_should_be_processed)
 	{
-		processHideButton(RS_BUTTON_SNAPSHOT, &delta_width, &buttons_freed_width);
+		processShrinkButtons(&delta_width);
+
+		if (delta_width < 0)
+		{
+			processHideButton(RS_BUTTON_SNAPSHOT, &delta_width, &buttons_freed_width);
+		}
 
 		if (delta_width < 0)
 		{
@@ -493,7 +501,7 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width)
 		if (delta_width < 0)
 		{
 			extra_shrink_width = -delta_width;
-			lldebugs << "There is no enough room for bottom tray, resizing still should be processed: " 
+			llwarns << "There is no enough width to reshape all children: " 
 				<< extra_shrink_width << llendl;
 		}
 
@@ -551,7 +559,7 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)
 		processShowButton(RS_BUTTON_SNAPSHOT, &available_width, &buttons_required_width);
 	}
 
-	// if we have to show some buttons but whidth increasing is not enough...
+	// if we have to show some buttons but width increasing is not enough...
 	if (buttons_required_width > 0 && delta_width < buttons_required_width)
 	{
 		// ... let's shrink nearby chat & chiclet panels
@@ -587,6 +595,8 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)
 	// shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels
 	delta_width -= buttons_required_width;
 
+	processExtendButtons(&delta_width);
+
 	// how many space can nearby chatbar take?
 	S32 chatbar_panel_width_ = mNearbyChatBar->getRect().getWidth();
 	if (delta_width > 0 && chatbar_panel_width_ < chatbar_panel_max_width)
@@ -656,6 +666,119 @@ void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* re
 	}
 }
 
+void LLBottomTray::processShrinkButtons(S32* required_width)
+{
+	processShrinkButton(RS_BUTTON_CAMERA, required_width);
+
+	if (*required_width < 0)
+	{
+		processShrinkButton(RS_BUTTON_MOVEMENT, required_width);
+	}
+	if (*required_width < 0)
+	{
+		processShrinkButton(RS_BUTTON_GESTURES, required_width);
+	}
+}
+
+void LLBottomTray::processShrinkButton(EResizeState processed_object_type, /*const std::string& panel_name, */S32* required_width)
+{
+	LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
+	if (NULL == panel)
+	{
+		lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
+		return;
+	}
+
+	if (panel->getVisible())
+	{
+		S32 panel_width = panel->getRect().getWidth();
+		S32 panel_min_width = 0;
+		std::string panel_name = panel->getName();
+		bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width, NULL);
+		S32 possible_shrink_width = panel_width - panel_min_width;
+
+		if (!success)
+		{
+			lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
+		}
+		// we have some space to free by shrinking the button
+		else if (possible_shrink_width > 0)
+		{
+			// let calculate real width to shrink
+
+			// 1. apply all possible width
+			*required_width += possible_shrink_width;
+
+			// 2. it it is too much... 
+			if (*required_width > 0)
+			{
+				// reduce applied shrunk width to the excessive value.
+				possible_shrink_width -= *required_width;
+				*required_width = 0;
+			}
+			panel->reshape(panel_width - possible_shrink_width, panel->getRect().getHeight());
+
+			lldebugs << "Shrunk panel: " << panel_name
+				<< ", shrunk width: " << possible_shrink_width
+				<< ", rest width to process: " << *required_width
+				<< llendl;
+		}
+	}
+}
+
+
+void LLBottomTray::processExtendButtons(S32* available_width)
+{
+	processExtendButton(RS_BUTTON_GESTURES, available_width);
+
+	if (*available_width > 0)
+	{
+		processExtendButton(RS_BUTTON_CAMERA, available_width);
+	}
+	if (*available_width > 0)
+	{
+		processExtendButton(RS_BUTTON_MOVEMENT, available_width);
+	}
+}
+
+void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32* available_width)
+{
+	LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
+	if (NULL == panel)
+	{
+		lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
+		return;
+	}
+
+	if (!panel->getVisible()) return;
+
+	S32 panel_max_width = mObjectDefaultWidthMap[processed_object_type];
+	S32 panel_width = panel->getRect().getWidth();
+	S32 possible_extend_width = panel_max_width - panel_width;
+
+	if (possible_extend_width > 0)
+	{
+		// let calculate real width to extend
+
+		// 1. apply all possible width
+		*available_width -= possible_extend_width;
+
+		// 2. it it is too much... 
+		if (*available_width < 0)
+		{
+			// reduce applied extended width to the excessive value.
+			possible_extend_width += *available_width;
+			*available_width = 0;
+		}
+		panel->reshape(panel_width + possible_extend_width, panel->getRect().getHeight());
+
+		lldebugs << "Extending panel: " << panel->getName()
+			<< ", extended width: " << possible_extend_width
+			<< ", rest width to process: " << *available_width
+			<< llendl;
+	}
+}
+
 bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const
 {
 	bool can_be_shown = mResizeState & processed_object_type;
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index 8989816bfec..97bcc23403a 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -98,7 +98,6 @@ class LLBottomTray
 		, RS_BUTTON_MOVEMENT	= 0x0010
 		, RS_BUTTON_GESTURES	= 0x0020
 		, RS_BUTTON_SPEAK		= 0x0040
-		, RS_RESIZABLE_BUTTONS			= /*RS_BUTTON_SNAPSHOT | */RS_BUTTON_CAMERA | RS_BUTTON_MOVEMENT | RS_BUTTON_GESTURES
 	}EResizeState;
 
 	S32 processWidthDecreased(S32 delta_width);
@@ -107,6 +106,24 @@ class LLBottomTray
 	bool processShowButton(EResizeState shown_object_type, S32* available_width, S32* buttons_required_width);
 	void processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width);
 
+	/**
+	 * Shrinks shown buttons to reduce total taken space.
+	 *
+	 * @param - required_width - width which buttons can use to be shrunk. It is a negative value.
+	 * It is increased on the value processed by buttons.
+	 */
+	void processShrinkButtons(S32* required_width);
+	void processShrinkButton(EResizeState processed_object_type, S32* required_width);
+
+	/**
+	 * Extends shown buttons to increase total taken space.
+	 *
+	 * @param - available_width - width which buttons can use to be extended. It is a positive value.
+	 * It is decreased on the value processed by buttons.
+	 */
+	void processExtendButtons(S32* available_width);
+	void processExtendButton(EResizeState processed_object_type, S32* available_width);
+
 	/**
 	 * Determines if specified by type object can be shown. It should be hidden by shrink before.
 	 *
@@ -140,6 +157,9 @@ class LLBottomTray
 	typedef std::map<EResizeState, LLPanel*> state_object_map_t;
 	state_object_map_t mStateProcessedObjectMap;
 
+	typedef std::map<EResizeState, S32> state_object_width_map_t;
+	state_object_width_map_t mObjectDefaultWidthMap;
+
 protected:
 
 	LLBottomTray(const LLSD& key = LLSD());
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index a902f505824..d2933c0c0ea 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -94,7 +94,7 @@
          min_height="28"
          width="82"
          top_delta="0"
-         min_width="82"
+         min_width="52"
          name="gesture_panel"
          user_resize="false">
          <gesture_combo_box
@@ -105,9 +105,13 @@
           name="Gesture"
           left="0"
           top="3"
-         use_ellipses="true"
           width="82"
-          tool_tip="Shows/hides gestures"/>
+          tool_tip="Shows/hides gestures">
+             <gesture_combo_box.drop_down_button
+              font="SansSerifSmall"
+              pad_right="10" 
+              use_ellipses="true" />
+         </gesture_combo_box>
         </layout_panel>
 		 <icon
          auto_resize="false"
@@ -131,7 +135,7 @@
          name="movement_panel"
          user_resize="false"
          width="80"
-         min_width="80">
+         min_width="49">
             <button
              follows="left|right"
              height="23"
@@ -167,7 +171,7 @@
          height="28"
          layout="topleft"
          min_height="28"
-         min_width="80"
+         min_width="49"
          name="cam_panel"
          user_resize="false"
          width="80">
-- 
GitLab