diff options
Diffstat (limited to 'indra/llui')
| -rw-r--r-- | indra/llui/lllayoutstack.cpp | 829 | ||||
| -rw-r--r-- | indra/llui/lllayoutstack.h | 95 | ||||
| -rw-r--r-- | indra/llui/llresizebar.cpp | 4 | ||||
| -rw-r--r-- | indra/llui/llresizebar.h | 1 | ||||
| -rw-r--r-- | indra/llui/llscrollcontainer.cpp | 99 | ||||
| -rw-r--r-- | indra/llui/llview.cpp | 5 | ||||
| -rw-r--r-- | indra/llui/llwindowshade.cpp | 11 | ||||
| -rw-r--r-- | indra/llui/llwindowshade.h | 3 | 
8 files changed, 597 insertions, 450 deletions
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 0e7060e22c..2f1c2a47c9 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -34,6 +34,10 @@  #include "llpanel.h"  #include "llresizebar.h"  #include "llcriticaldamp.h" +#include "boost/foreach.hpp" + +static const F32 MIN_FRACTIONAL_SIZE = 0.0001f; +static const F32 MAX_FRACTIONAL_SIZE = 1.f;  static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack");  static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel"); @@ -49,39 +53,29 @@ void LLLayoutStack::OrientationNames::declareValues()  //  LLLayoutPanel::Params::Params()	  :	expanded_min_dim("expanded_min_dim", 0), -	min_dim("min_dim", 0), -	max_dim("max_dim", S32_MAX), -	user_resize("user_resize", true), +	min_dim("min_dim", -1), +	user_resize("user_resize", false),  	auto_resize("auto_resize", true)  {  	addSynonym(min_dim, "min_width");  	addSynonym(min_dim, "min_height"); -	addSynonym(max_dim, "max_width"); -	addSynonym(max_dim, "max_height");  }  LLLayoutPanel::LLLayoutPanel(const Params& p)	  :	LLPanel(p), -	mExpandedMinDimSpecified(false), -	mExpandedMinDim(p.min_dim), +	mExpandedMinDim(p.expanded_min_dim.isProvided() ? p.expanded_min_dim : p.min_dim),   	mMinDim(p.min_dim),  - 	mMaxDim(p.max_dim),    	mAutoResize(p.auto_resize),   	mUserResize(p.user_resize),  	mCollapsed(FALSE),  	mCollapseAmt(0.f),  	mVisibleAmt(1.f), // default to fully visible  	mResizeBar(NULL), -	mFractionalSize(0.f), +	mFractionalSize(MIN_FRACTIONAL_SIZE), +	mTargetDim(0), +	mIgnoreReshape(false),  	mOrientation(LLLayoutStack::HORIZONTAL)  { -	// Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value -	if (p.expanded_min_dim.isProvided()) -	{ -		mExpandedMinDimSpecified = true; -		mExpandedMinDim = p.expanded_min_dim(); -	} -	  	// panels initialized as hidden should not start out partially visible  	if (!getVisible())  	{ @@ -103,33 +97,83 @@ LLLayoutPanel::~LLLayoutPanel()  	mResizeBar = NULL;  } -void LLLayoutPanel::reshape(S32 width, S32 height, BOOL called_from_parent) +F32 LLLayoutPanel::getAutoResizeFactor() const +{ +	return mVisibleAmt * (1.f - mCollapseAmt); +} +  +F32 LLLayoutPanel::getVisibleAmount() const +{ +	return mVisibleAmt; +} + +S32 LLLayoutPanel::getLayoutDim() const +{ +	return llround((F32)((mOrientation == LLLayoutStack::HORIZONTAL) +					? getRect().getWidth() +					: getRect().getHeight())); +} +  +S32 LLLayoutPanel::getVisibleDim() const +{ +	F32 min_dim = getRelevantMinDim(); +	return llround(mVisibleAmt +					* (min_dim +						+ (((F32)mTargetDim - min_dim) * (1.f - mCollapseAmt)))); +} +  +void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientation ) +{ +	mOrientation = orientation; +	S32 layout_dim = llround((F32)((mOrientation == LLLayoutStack::HORIZONTAL) +		? getRect().getWidth() +		: getRect().getHeight())); + +	mTargetDim = llmax(layout_dim, getMinDim()); +} +  +void LLLayoutPanel::setVisible( BOOL visible )  { -	if (mOrientation == LLLayoutStack::HORIZONTAL) +	if (visible != getVisible())  	{ -		mFractionalSize += width - llround(mFractionalSize); +		LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent()); +		if (stackp) +		{ +			stackp->mNeedsLayout = true; +		}  	} -	else +	LLPanel::setVisible(visible); +} + +void LLLayoutPanel::reshape( S32 width, S32 height, BOOL called_from_parent /*= TRUE*/ ) +{ +	if (width == getRect().getWidth() && height == getRect().getHeight()) return; + +	if (!mIgnoreReshape && mAutoResize == false)  	{ -		mFractionalSize += height - llround(mFractionalSize); +		mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height; +		LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent()); +		if (stackp) +		{ +			stackp->mNeedsLayout = true; +		}  	}  	LLPanel::reshape(width, height, called_from_parent);  } -F32 LLLayoutPanel::getCollapseFactor() +void LLLayoutPanel::handleReshape(const LLRect& new_rect, bool by_user)  { -	if (mOrientation == LLLayoutStack::HORIZONTAL) +	LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent()); +	if (stackp)  	{ -		F32 collapse_amt =  -			clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getWidth())); -		return mVisibleAmt * collapse_amt; -	} -	else -	{ -		F32 collapse_amt =  -			clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getHeight()))); -		return mVisibleAmt * collapse_amt; +		stackp->mNeedsLayout = true; +		if (by_user) +		{ +			// tell layout stack to account for new shape +			stackp->updatePanelRect(this, new_rect); +		}  	} +	LLPanel::handleReshape(new_rect, by_user);  }  // @@ -142,20 +186,21 @@ LLLayoutStack::Params::Params()  	clip("clip", true),  	open_time_constant("open_time_constant", 0.02f),  	close_time_constant("close_time_constant", 0.03f), +	resize_bar_overlap("resize_bar_overlap", 1),  	border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0))  {}  LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)   :	LLView(p), -	mMinWidth(0), -	mMinHeight(0),  	mPanelSpacing(p.border_size),  	mOrientation(p.orientation),  	mAnimate(p.animate),  	mAnimatedThisFrame(false), +	mNeedsLayout(true),  	mClip(p.clip),  	mOpenTimeConstant(p.open_time_constant), -	mCloseTimeConstant(p.close_time_constant) +	mCloseTimeConstant(p.close_time_constant), +	mResizeBarOverlap(p.resize_bar_overlap)  {}  LLLayoutStack::~LLLayoutStack() @@ -169,26 +214,26 @@ void LLLayoutStack::draw()  {  	updateLayout(); -	e_panel_list_t::iterator panel_it; -	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) +	// always clip to stack itself +	LLLocalClipRect clip(getLocalRect()); +	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)  	{  		// clip to layout rectangle, not bounding rectangle -		LLRect clip_rect = (*panel_it)->getRect(); +		LLRect clip_rect = panelp->getRect();  		// scale clipping rectangle by visible amount  		if (mOrientation == HORIZONTAL)  		{ -			clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor()); +			clip_rect.mRight = clip_rect.mLeft + panelp->getVisibleDim();  		}  		else  		{ -			clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor()); +			clip_rect.mBottom = clip_rect.mTop - panelp->getVisibleDim();  		} -		LLPanel* panelp = (*panel_it); - -		LLLocalClipRect clip(clip_rect, mClip); -		// only force drawing invisible children if visible amount is non-zero -		drawChild(panelp, 0, 0, !clip_rect.isEmpty()); +		{LLLocalClipRect clip(clip_rect, mClip); +			// only force drawing invisible children if visible amount is non-zero +			drawChild(panelp, 0, 0, !clip_rect.isEmpty()); +		}  	}  	mAnimatedThisFrame = false;  } @@ -201,12 +246,10 @@ void LLLayoutStack::removeChild(LLView* view)  	{  		mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));  		delete embedded_panelp; +		updateFractionalSizes(); +		mNeedsLayout = true;  	} -	// need to update resizebars - -	calcMinExtents(); -  	LLView::removeChild(view);  } @@ -221,29 +264,15 @@ bool LLLayoutStack::addChild(LLView* child, S32 tab_group)  	LLLayoutPanel* panelp = dynamic_cast<LLLayoutPanel*>(child);  	if (panelp)  	{ -		panelp->mFractionalSize = (mOrientation == HORIZONTAL) -									? panelp->getRect().getWidth() -									: panelp->getRect().getHeight();  		panelp->setOrientation(mOrientation);  		mPanels.push_back(panelp); +		createResizeBar(panelp); +		mNeedsLayout = true;  	} -	return LLView::addChild(child, tab_group); -} +	BOOL result = LLView::addChild(child, tab_group); -void LLLayoutStack::movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front) -{ -	LLLayoutPanel* embedded_panel_to_move = findEmbeddedPanel(panel_to_move); -	LLLayoutPanel* embedded_target_panel = move_to_front ? *mPanels.begin() : findEmbeddedPanel(target_panel); - -	if (!embedded_panel_to_move || !embedded_target_panel || embedded_panel_to_move == embedded_target_panel) -	{ -		llwarns << "One of the panels was not found in stack or NULL was passed instead of valid panel" << llendl; -		return; -	} -	e_panel_list_t::iterator it = std::find(mPanels.begin(), mPanels.end(), embedded_panel_to_move); -	mPanels.erase(it); -	it = move_to_front ? mPanels.begin() : std::find(mPanels.begin(), mPanels.end(), embedded_target_panel); -	mPanels.insert(it, embedded_panel_to_move); +	updateFractionalSizes(); +	return result;  }  void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate) @@ -258,84 +287,274 @@ void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate)  	}  } -void LLLayoutStack::removePanel(LLPanel* panel) -{ -	removeChild(panel); -} -  void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)  {  	LLLayoutPanel* panel_container = findEmbeddedPanel(panel);  	if (!panel_container) return;  	panel_container->mCollapsed = collapsed; +	mNeedsLayout = true;  } -void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize) -{ -	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); +static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks"); -	if (panel) +void LLLayoutStack::updateLayout() +{	 +	LLFastTimer ft(FTM_UPDATE_LAYOUT); + +	if (!mNeedsLayout) return; + +	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(); + +	// first, assign minimum dimensions +	LLLayoutPanel* panelp = NULL; +	BOOST_FOREACH(panelp, mPanels)  	{ -		panel->mAutoResize = auto_resize; +		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;  	} -} -void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize) +	llassert(total_visible_fraction < 1.01f); + +	// don't need spacing after last panel +	space_to_distribute += panelp ? llround((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0; + +	F32 fraction_distributed = 0.f; +	if (space_to_distribute > 0 && total_visible_fraction > 0.f) +	{	// give space proportionally to visible auto resize panels +		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +		{ +			if (panelp->mAutoResize) +			{ +				F32 fraction_to_distribute = (panelp->mFractionalSize * panelp->getAutoResizeFactor()) / (total_visible_fraction); +				S32 delta = llround((F32)space_to_distribute * fraction_to_distribute); +				fraction_distributed += fraction_to_distribute; +				panelp->mTargetDim += 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)); + +		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +		{ +			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; +			} +		} +	} + +	F32 cur_pos = (mOrientation == HORIZONTAL) ? 0.f : (F32)getRect().getHeight(); + +	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +	{ +		F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim); +		F32 panel_visible_dim = panelp->getVisibleDim(); + +		LLRect panel_rect; +		if (mOrientation == HORIZONTAL) +		{ +			panel_rect.setLeftTopAndSize(llround(cur_pos), +										getRect().getHeight(), +										llround(panel_dim), +										getRect().getHeight()); +		} +		else +		{ +			panel_rect.setLeftTopAndSize(0, +										llround(cur_pos), +										getRect().getWidth(), +										llround(panel_dim)); +		} +		panelp->setIgnoreReshape(true); +		panelp->setShape(panel_rect); +		panelp->setIgnoreReshape(false); + +		LLRect resize_bar_rect(panel_rect); + +		F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount(); +		if (mOrientation == HORIZONTAL) +		{ +			resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap; +			resize_bar_rect.mRight = panel_rect.mRight + (S32)(llround(panel_spacing)) + mResizeBarOverlap; + +			cur_pos += panel_visible_dim + panel_spacing; +		} +		else //VERTICAL +		{ +			resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap; +			resize_bar_rect.mBottom = panel_rect.mBottom - (S32)(llround(panel_spacing)) - mResizeBarOverlap; + +			cur_pos -= panel_visible_dim + panel_spacing; +		} +		panelp->mResizeBar->setShape(resize_bar_rect); +	} + +	updateResizeBarLimits(); + +	// clear animation flag at end, since panel resizes will set it +	// and leave it set if there is any animation in progress +	mNeedsLayout = animation_in_progress; +} // end LLLayoutStack::updateLayout + +LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const  { -	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); +	if (!panelp) return NULL; -	if (panel) +	e_panel_list_t::const_iterator panel_it; +	BOOST_FOREACH(LLLayoutPanel* p, mPanels)  	{ -		panel->mUserResize = user_resize; +		if (p == panelp) +		{ +			return p; +		}  	} +	return NULL;  } -bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_dimp) +LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const  { -	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); +	LLLayoutPanel* result = NULL; -	if (panel && min_dimp) +	BOOST_FOREACH(LLLayoutPanel* p, mPanels)  	{ -		*min_dimp = panel->getRelevantMinDim(); +		if (p->getName() == name) +		{ +			result = p; +			break; +		}  	} -	return NULL != panel; +	return result;  } -bool LLLayoutStack::getPanelMaxSize(const std::string& panel_name, S32* max_dimp) +void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)  { -	LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); +	BOOST_FOREACH(LLLayoutPanel* lp, mPanels) +	{ +		if (lp->mResizeBar == NULL) +		{ +			LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; +			LLRect resize_bar_rect = getRect(); -	if (panel) +			LLResizeBar::Params resize_params; +			resize_params.name("resize"); +			resize_params.resizing_view(lp); +			resize_params.min_size(lp->getRelevantMinDim()); +			resize_params.side(side); +			resize_params.snapping_enabled(false); +			LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params); +			lp->mResizeBar = resize_bar; +			LLView::addChild(resize_bar, 0); +		} +	} +	// bring all resize bars to the front so that they are clickable even over the panels +	// with a bit of overlap +	for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)  	{ -		if (max_dimp) *max_dimp = panel->mMaxDim; +		LLResizeBar* resize_barp = (*panel_it)->mResizeBar; +		sendChildToFront(resize_barp);  	} +} -	return NULL != panel; +// update layout stack animations, etc. once per frame +// NOTE: we use this to size world view based on animating UI, *before* we draw the UI +// we might still need to call updateLayout during UI draw phase, in case UI elements +// are resizing themselves dynamically +//static  +void LLLayoutStack::updateClass() +{ +	for (instance_iter it = beginInstances(); it != endInstances(); ++it) +	{ +		it->updateLayout(); +	}  } -static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks"); -void LLLayoutStack::updateLayout(BOOL force_resize) +void LLLayoutStack::updateFractionalSizes()  { -	LLFastTimer ft(FTM_UPDATE_LAYOUT); -	static LLUICachedControl<S32> resize_bar_overlap ("UIResizeBarOverlap", 0); -	calcMinExtents(); -	createResizeBars(); +	F32 total_resizable_dim = 0; +	S32 num_auto_resize_panels = 0; -	// calculate current extents -	F32 total_size = 0.f; +	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +	{ +		if (panelp->mAutoResize) +		{ +			total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim()); +			num_auto_resize_panels++; +		} +	} +	F32 total_fractional_size = 0.f; +	 +	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +	{ +		if (panelp->mAutoResize) +		{ +			F32 panel_resizable_dim = llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim())); +			panelp->mFractionalSize = panel_resizable_dim > 0.f  +										? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE) +										: MIN_FRACTIONAL_SIZE; +			total_fractional_size += panelp->mFractionalSize; +			llassert(!llisnan(panelp->mFractionalSize)); +		} +	} + +	if (total_fractional_size == 0.f) +	{ // equal distribution +		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +		{ +			if (panelp->mAutoResize) +			{ +				panelp->mFractionalSize = MAX_FRACTIONAL_SIZE / (F32)num_auto_resize_panels; +			} +		} +	} +	else +	{ // renormalize +		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +		{ +			if (panelp->mAutoResize) +			{ +				panelp->mFractionalSize /= total_fractional_size; +			} +		} +	} +} + +bool LLLayoutStack::animatePanels() +{ +	bool animation_in_progress = false; +	  	//  	// animate visibility  	// -	e_panel_list_t::iterator panel_it; -	for (panel_it = mPanels.begin(); panel_it != mPanels.end();	++panel_it) +	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)  	{ -		LLLayoutPanel* panelp = (*panel_it); -		if (panelp->getVisible())  +		if (panelp->getVisible())  		{ -			if (mAnimate) +			if (mAnimate && panelp->mVisibleAmt < 1.f)  			{  				if (!mAnimatedThisFrame)  				{ @@ -345,15 +564,21 @@ void LLLayoutStack::updateLayout(BOOL force_resize)  						panelp->mVisibleAmt = 1.f;  					}  				} +				 +				animation_in_progress = true;  			}  			else  			{ -				panelp->mVisibleAmt = 1.f; +				if (panelp->mVisibleAmt != 1.f) +				{ +					panelp->mVisibleAmt = 1.f; +					animation_in_progress = true; +				}  			}  		}  		else // not visible  		{ -			if (mAnimate) +			if (mAnimate && panelp->mVisibleAmt > 0.f)  			{  				if (!mAnimatedThisFrame)  				{ @@ -363,297 +588,213 @@ void LLLayoutStack::updateLayout(BOOL force_resize)  						panelp->mVisibleAmt = 0.f;  					}  				} + +				animation_in_progress = true;  			}  			else  			{ -				panelp->mVisibleAmt = 0.f; +				if (panelp->mVisibleAmt != 0.f) +				{ +					panelp->mVisibleAmt = 0.f; +					animation_in_progress = true; +				}  			}  		}  		F32 collapse_state = panelp->mCollapsed ? 1.f : 0.f; -		panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); - -        total_size += panelp->mFractionalSize * panelp->getCollapseFactor(); -        // want n-1 panel gaps for n panels -		if (panel_it != mPanels.begin()) -		{ -			total_size += mPanelSpacing; -		} -	} - -	S32 num_resizable_panels = 0; -	F32 shrink_headroom_available = 0.f; -	F32 shrink_headroom_total = 0.f; -	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) -	{ -		LLLayoutPanel* panelp = (*panel_it); - -		// panels that are not fully visible do not count towards shrink headroom -		if (panelp->getCollapseFactor() < 1.f)  -		{ -			continue; -		} - -		F32 cur_size = panelp->mFractionalSize; -		F32 min_size = (F32)panelp->getRelevantMinDim(); -		 -		// if currently resizing a panel or the panel is flagged as not automatically resizing -		// only track total available headroom, but don't use it for automatic resize logic -		if (panelp->mResizeBar->hasMouseCapture()  -			|| (!panelp->mAutoResize  -				&& !force_resize)) -		{ -			shrink_headroom_total += cur_size - min_size; -		} -		else -		{ -			num_resizable_panels++; -			 -			shrink_headroom_available += cur_size - min_size; -			shrink_headroom_total += cur_size - min_size; -		} -	} - -	// calculate how many pixels need to be distributed among layout panels -	// positive means panels need to grow, negative means shrink -	F32 pixels_to_distribute = (mOrientation == HORIZONTAL) -							? getRect().getWidth() - total_size -							: getRect().getHeight() - total_size; - -	// now we distribute the pixels... -	F32 cur_x = 0.f; -	F32 cur_y = (F32)getRect().getHeight(); - -	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) -	{ -		LLLayoutPanel* panelp = (*panel_it); - -		F32 min_size = panelp->getRelevantMinDim(); -		F32 delta_size = 0.f; - -		// if panel can automatically resize (not animating, and resize flag set)... -		if (panelp->getCollapseFactor() == 1.f  -			&& (force_resize || panelp->mAutoResize)  -			&& !panelp->mResizeBar->hasMouseCapture())  +		if (panelp->mCollapseAmt != collapse_state)  		{ -			if (pixels_to_distribute < 0.f) +			if (!mAnimatedThisFrame)  			{ -				// shrink proportionally to amount over minimum -				// so we can do this in one pass -				delta_size = (shrink_headroom_available > 0.f)  -					? pixels_to_distribute * ((F32)(panelp->mFractionalSize - min_size) / shrink_headroom_available)  -					: 0.f; -				shrink_headroom_available -= (panelp->mFractionalSize - min_size); +				panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant));  			} -			else +			animation_in_progress = true; +			 +			if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f)  			{ -				// grow all elements equally -				delta_size = pixels_to_distribute / (F32)num_resizable_panels; -				num_resizable_panels--; +				panelp->mCollapseAmt = collapse_state;  			} -			 -			panelp->mFractionalSize = llmax(min_size, panelp->mFractionalSize + delta_size); -			pixels_to_distribute -= delta_size;  		} +	} -		// adjust running headroom count based on new sizes -		shrink_headroom_total += delta_size; +	mAnimatedThisFrame = true; -		LLRect panel_rect; -		if (mOrientation == HORIZONTAL) -		{ -			panel_rect.setLeftTopAndSize(llround(cur_x),  -										llround(cur_y),  -										llround(panelp->mFractionalSize),  -										getRect().getHeight()); -		} -		else -		{ -			panel_rect.setLeftTopAndSize(llround(cur_x),  -										llround(cur_y),  -										getRect().getWidth(),  -										llround(panelp->mFractionalSize)); -		} -		panelp->setShape(panel_rect); +	return animation_in_progress; +} -		LLRect resize_bar_rect = panel_rect; -		if (mOrientation == HORIZONTAL) -		{ -			resize_bar_rect.mLeft = panel_rect.mRight - resize_bar_overlap; -			resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + resize_bar_overlap; -		} -		else -		{ -			resize_bar_rect.mTop = panel_rect.mBottom + resize_bar_overlap; -			resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - resize_bar_overlap; -		} -		(*panel_it)->mResizeBar->setRect(resize_bar_rect); +void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& new_rect ) +{ +	S32 new_dim = (mOrientation == HORIZONTAL) +					? new_rect.getWidth() +					: new_rect.getHeight(); +	S32 delta_dim = new_dim - resized_panel->getVisibleDim(); +	if (delta_dim == 0) return; -		F32 size = ((*panel_it)->mFractionalSize * (*panel_it)->getCollapseFactor()) + (F32)mPanelSpacing; -		if (mOrientation == HORIZONTAL) -		{ -			cur_x += size; -		} -		else //VERTICAL -		{ -			cur_y -= size; -		} -	} +	F32 total_visible_fraction = 0.f; +	F32 delta_auto_resize_headroom = 0.f; +	F32 total_auto_resize_headroom = 0.f; -	// update resize bars with new limits -	LLLayoutPanel* last_resizeable_panel = NULL; -	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) -	{ -		LLLayoutPanel* panelp = (*panel_it); -		S32 relevant_min = panelp->getRelevantMinDim(); +	LLLayoutPanel* other_resize_panel = NULL; +	LLLayoutPanel* following_panel = NULL; -		if (mOrientation == HORIZONTAL) +	BOOST_REVERSE_FOREACH(LLLayoutPanel* panelp, mPanels) +	{ +		if (panelp->mAutoResize)  		{ -			(*panel_it)->mResizeBar->setResizeLimits( -				relevant_min,  -				relevant_min + llround(shrink_headroom_total)); +			total_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); +			total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor();  		} -		else //VERTICAL + +		if (panelp == resized_panel)  		{ -			(*panel_it)->mResizeBar->setResizeLimits( -				relevant_min,  -				relevant_min + llround(shrink_headroom_total)); +			other_resize_panel = following_panel;  		} -		// toggle resize bars based on panel visibility, resizability, etc -		BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize; -		(*panel_it)->mResizeBar->setVisible(resize_bar_enabled); - -		if ((*panel_it)->mUserResize || (*panel_it)->mAutoResize) +		if (panelp->getVisible() && !panelp->mCollapsed)  		{ -			last_resizeable_panel = (*panel_it); +			following_panel = panelp;  		}  	} -	// hide last resize bar as there is nothing past it -	// resize bars need to be in between two resizable panels -	if (last_resizeable_panel) +	if (resized_panel->mAutoResize == FALSE)  	{ -		last_resizeable_panel->mResizeBar->setVisible(FALSE); +		delta_auto_resize_headroom += -delta_dim;  	} - -	// not enough room to fit existing contents -	if (force_resize == FALSE -		// layout did not complete by reaching target position -		&& ((mOrientation == VERTICAL && llround(cur_y) != -mPanelSpacing) -			|| (mOrientation == HORIZONTAL && llround(cur_x) != getRect().getWidth() + mPanelSpacing))) +	if (other_resize_panel && other_resize_panel->mAutoResize == FALSE)  	{ -		// do another layout pass with all stacked elements contributing -		// even those that don't usually resize -		llassert_always(force_resize == FALSE); -		updateLayout(TRUE); +		delta_auto_resize_headroom += delta_dim;  	} -	 mAnimatedThisFrame = true; -} // end LLLayoutStack::updateLayout +	F32 fraction_given_up = 0.f; +	F32 fraction_remaining = 1.f; +	F32 updated_auto_resize_headroom = total_auto_resize_headroom + delta_auto_resize_headroom; - -LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const -{ -	if (!panelp) return NULL; - -	e_panel_list_t::const_iterator panel_it; -	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) +	enum  	{ -		if ((*panel_it) == panelp) -		{ -			return *panel_it; -		} -	} -	return NULL; -} +		BEFORE_RESIZED_PANEL, +		RESIZED_PANEL, +		NEXT_PANEL, +		AFTER_RESIZED_PANEL +	} which_panel = BEFORE_RESIZED_PANEL; -LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const -{ -	LLLayoutPanel* result = NULL; - -	for (e_panel_list_t::const_iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) +	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)  	{ -		LLLayoutPanel* p = *panel_it; +		if (!panelp->getVisible() || panelp->mCollapsed) continue; -		if (p->getName() == name) +		if (panelp == resized_panel)  		{ -			result = p; -			break; +			which_panel = RESIZED_PANEL;  		} -	} - -	return result; -} - -// Compute sum of min_width or min_height of children -void LLLayoutStack::calcMinExtents() -{ -	mMinWidth = 0; -	mMinHeight = 0; -	e_panel_list_t::iterator panel_it; -	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) -	{ -		if (mOrientation == HORIZONTAL) +		switch(which_panel)  		{ -            mMinWidth += (*panel_it)->getRelevantMinDim(); -			if (panel_it != mPanels.begin()) +		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 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor, +													MIN_FRACTIONAL_SIZE, +													MAX_FRACTIONAL_SIZE); +				F32 fraction_delta = (new_fractional_size - panelp->mFractionalSize); +				fraction_given_up -= fraction_delta; +				fraction_remaining -= panelp->mFractionalSize; +				panelp->mFractionalSize += fraction_delta; +				llassert(!llisnan(panelp->mFractionalSize)); +			} +			else  			{ -				mMinWidth += mPanelSpacing; +				// leave non auto-resize panels alone  			} -		} -		else //VERTICAL -		{ -			mMinHeight += (*panel_it)->getRelevantMinDim(); -			if (panel_it != mPanels.begin()) +			break; +		case RESIZED_PANEL: +			if (panelp->mAutoResize) +			{	// freeze new size as fraction +				F32 new_fractional_size = (updated_auto_resize_headroom == 0.f) +					? MAX_FRACTIONAL_SIZE +					: llclamp((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); +				fraction_given_up -= new_fractional_size - panelp->mFractionalSize; +				fraction_remaining -= panelp->mFractionalSize; +				panelp->mFractionalSize = new_fractional_size; +				llassert(!llisnan(panelp->mFractionalSize)); +			} +			else +			{	// freeze new size as original size +				panelp->mTargetDim = new_dim; +				fraction_remaining -= fraction_given_up; +			} +			which_panel = NEXT_PANEL; +			break; +		case NEXT_PANEL: +			if (panelp->mAutoResize) +			{ +				fraction_remaining -= panelp->mFractionalSize; +				if (fraction_given_up != 0.f) +				{ +					panelp->mFractionalSize = llclamp(panelp->mFractionalSize + fraction_given_up, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); +					fraction_given_up = 0.f; +				} +				else +				{ +					F32 new_fractional_size = llclamp((F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom)  +														/ updated_auto_resize_headroom, +													MIN_FRACTIONAL_SIZE, +													MAX_FRACTIONAL_SIZE); +					fraction_given_up -= new_fractional_size - panelp->mFractionalSize; +					panelp->mFractionalSize = new_fractional_size; +				} +			} +			else +			{ +				panelp->mTargetDim -= delta_dim; +			} +			which_panel = AFTER_RESIZED_PANEL; +			break; +		case AFTER_RESIZED_PANEL: +			if (panelp->mAutoResize)  			{ -				mMinHeight += mPanelSpacing; +				panelp->mFractionalSize = llclamp(panelp->mFractionalSize + (panelp->mFractionalSize / fraction_remaining) * fraction_given_up, +												MIN_FRACTIONAL_SIZE, +												MAX_FRACTIONAL_SIZE);  			} +		default: +			break;  		}  	}  } -void LLLayoutStack::createResizeBars() +void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)  { -	for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) +	mNeedsLayout = true; +	LLView::reshape(width, height, called_from_parent); +} + +void LLLayoutStack::updateResizeBarLimits() +{ +	LLLayoutPanel* previous_visible_panelp = NULL; +	BOOST_REVERSE_FOREACH(LLLayoutPanel* visible_panelp, mPanels)  	{ -		LLLayoutPanel* lp = (*panel_it); -		if (lp->mResizeBar == NULL) +		if (!visible_panelp->getVisible() || visible_panelp->mCollapsed)  		{ -			LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; -			LLRect resize_bar_rect = getRect(); - -			LLResizeBar::Params resize_params; -			resize_params.name("resize"); -			resize_params.resizing_view(lp); -			resize_params.min_size(lp->getRelevantMinDim()); -			resize_params.side(side); -			resize_params.snapping_enabled(false); -			LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params); -			lp->mResizeBar = resize_bar; -			LLView::addChild(resize_bar, 0); +			visible_panelp->mResizeBar->setVisible(FALSE); +			continue; +		} -			// bring all resize bars to the front so that they are clickable even over the panels -			// with a bit of overlap -			for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) -			{ -				LLResizeBar* resize_barp = (*panel_it)->mResizeBar; -				sendChildToFront(resize_barp); -			} +		// toggle resize bars based on panel visibility, resizability, etc +		if (previous_visible_panelp +			&& (visible_panelp->mUserResize || previous_visible_panelp->mUserResize)				// one of the pair is user resizable +			&& (visible_panelp->mAutoResize || visible_panelp->mUserResize)							// current panel is resizable +			&& (previous_visible_panelp->mAutoResize || previous_visible_panelp->mUserResize))		// previous panel is resizable +		{ +			visible_panelp->mResizeBar->setVisible(TRUE); +			S32 previous_panel_headroom = previous_visible_panelp->getVisibleDim() - previous_visible_panelp->getRelevantMinDim(); +			visible_panelp->mResizeBar->setResizeLimits(visible_panelp->getRelevantMinDim(),  +														visible_panelp->getVisibleDim() + previous_panel_headroom); +		} +		else +		{ +			visible_panelp->mResizeBar->setVisible(FALSE);  		} -	} -} -// update layout stack animations, etc. once per frame -// NOTE: we use this to size world view based on animating UI, *before* we draw the UI -// we might still need to call updateLayout during UI draw phase, in case UI elements -// are resizing themselves dynamically -//static  -void LLLayoutStack::updateClass() -{ -	for (instance_iter it = beginInstances(); it != endInstances(); ++it) -	{ -		it->updateLayout(); +		previous_visible_panelp = visible_panelp;  	}  } diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 3b308a359d..efe93f6def 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -5,7 +5,7 @@   *   * $LicenseInfo:firstyear=2001&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2010, Linden Reshasearch, Inc.   *    * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -60,6 +60,7 @@ public:  								clip;  		Optional<F32>			open_time_constant,  								close_time_constant; +		Optional<S32>			resize_bar_overlap;  		Params();  	}; @@ -72,12 +73,11 @@ public:  	/*virtual*/ void removeChild(LLView*);  	/*virtual*/ BOOL postBuild();  	/*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); +	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); +  	static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); -	S32 getMinWidth() const { return mMinWidth; } -	S32 getMinHeight() const { return mMinHeight; } -	  	typedef enum e_animate  	{  		NO_ANIMATE, @@ -85,47 +85,24 @@ public:  	} EAnimate;  	void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE); -	void removePanel(LLPanel* panel);  	void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);  	S32 getNumPanels() { return mPanels.size(); } -	/** -	 * Moves panel_to_move before target_panel inside layout stack (both panels should already be there). -	 * If move_to_front is true target_panel is ignored and panel_to_move is moved to the beginning of mPanels -	 */ -	void movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front = false); - -	void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize); -	void setPanelUserResize(const std::string& panel_name, BOOL user_resize); -	 -	/** -	 * Gets minimal dimension along layout_stack axis of the specified by name panel. -	 * -	 * @returns true if specified by panel_name internal panel exists, false otherwise. -	 */ -	bool getPanelMinSize(const std::string& panel_name, S32* min_dimp); - -	/** -	 * Gets maximal dimension along layout_stack axis of the specified by name panel. -	 * -	 * @returns true if specified by panel_name internal panel exists, false otherwise. -	 */ -	bool getPanelMaxSize(const std::string& panel_name, S32* max_dim); -	 -	void updateLayout(BOOL force_resize = FALSE); -	 + +	void updateLayout(); +  	S32 getPanelSpacing() const { return mPanelSpacing; } -	BOOL getAnimate () const { return mAnimate; } -	void setAnimate (BOOL animate) { mAnimate = animate; }  	static void updateClass();  protected:  	LLLayoutStack(const Params&);  	friend class LLUICtrlFactory; +	friend class LLLayoutPanel;  private: -	void createResizeBars(); -	void calcMinExtents(); +	void updateResizeBarLimits(); +	bool animatePanels(); +	void createResizeBar(LLLayoutPanel* panel);  	const ELayoutOrientation mOrientation; @@ -134,17 +111,19 @@ private:  	LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;  	LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const; +	void updateFractionalSizes(); +	void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect ); -	S32 mMinWidth;  // calculated by calcMinExtents -	S32 mMinHeight;  // calculated by calcMinExtents  	S32 mPanelSpacing;  	// true if we already applied animation this frame  	bool mAnimatedThisFrame;  	bool mAnimate;  	bool mClip; -	F32 mOpenTimeConstant; -	F32 mCloseTimeConstant; +	F32  mOpenTimeConstant; +	F32  mCloseTimeConstant; +	bool mNeedsLayout; +	S32  mResizeBarOverlap;  }; // end class LLLayoutStack @@ -156,8 +135,7 @@ public:  	struct Params : public LLInitParam::Block<Params, LLPanel::Params>  	{  		Optional<S32>			expanded_min_dim, -								min_dim, -								max_dim; +								min_dim;  		Optional<bool>			user_resize,  								auto_resize; @@ -168,16 +146,19 @@ public:  	void initFromParams(const Params& p); +	void handleReshape(const LLRect& new_rect, bool by_user); +  	void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); +	 -	S32 getMinDim() const { return mMinDim; } -	void setMinDim(S32 value) { mMinDim = value; if (!mExpandedMinDimSpecified) mExpandedMinDim = value; } +	void setVisible(BOOL visible); -	S32 getMaxDim() const { return mMaxDim; } -	void setMaxDim(S32 value) { mMaxDim = value; } +	S32 getLayoutDim() const; +	S32 getMinDim() const { return (mMinDim >= 0 || mAutoResize) ? llmax(0, mMinDim) : getLayoutDim(); } +	void setMinDim(S32 value) { mMinDim = value; } -	S32 getExpandedMinDim() const { return mExpandedMinDim; } -	void setExpandedMinDim(S32 value) { mExpandedMinDim = value; mExpandedMinDimSpecified = true; } +	S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : mMinDim; } +	void setExpandedMinDim(S32 value) { mExpandedMinDim = value; }  	S32 getRelevantMinDim() const  	{ @@ -185,29 +166,35 @@ public:  		if (!mCollapsed)  		{ -			min_dim = mExpandedMinDim; +			min_dim = getExpandedMinDim();  		}  		return min_dim;  	} -	F32 getCollapseFactor(); -	void setOrientation(LLLayoutStack::ELayoutOrientation orientation) { mOrientation = orientation; } +	F32 getAutoResizeFactor() const; +	F32 getVisibleAmount() const; +	S32 getVisibleDim() const; + +	void setOrientation(LLLayoutStack::ELayoutOrientation orientation); +	void storeOriginalDim(); + +	void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; }  protected:  	LLLayoutPanel(const Params& p); -	bool	mExpandedMinDimSpecified; +	const bool	mAutoResize; +	const bool	mUserResize; +  	S32		mExpandedMinDim; -	  	S32		mMinDim; -	S32		mMaxDim; -	bool	mAutoResize; -	bool	mUserResize;  	bool	mCollapsed;  	F32		mVisibleAmt;  	F32		mCollapseAmt;  	F32		mFractionalSize; +	S32		mTargetDim; +	bool	mIgnoreReshape;  	LLLayoutStack::ELayoutOrientation mOrientation;  	class LLResizeBar* mResizeBar;  }; diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index 02f60c76fa..87aeb4d7a7 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -79,6 +79,8 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)  BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask)  { +	if (!canResize()) return FALSE; +  	// Route future Mouse messages here preemptively.  (Release on mouse up.)  	// No handler needed for focus lost since this clas has no state that depends on it.  	gFocusMgr.setMouseCapture( this ); @@ -243,7 +245,7 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)  		handled = TRUE;  	} -	if( handled ) +	if( handled && canResize() )  	{  		switch( mSide )  		{ diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 0725fbd846..6daf191918 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -70,6 +70,7 @@ public:  	void			setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; }  	void			setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; }  	void			setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; } +	bool			canResize() { return getEnabled() && mMaxSize > mMinSize; }  private:  	S32				mDragLastScreenX; diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index fe3f688fc5..ad4cc20d9a 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -424,63 +424,66 @@ void LLScrollContainer::draw()  		focusFirstItem();  	} -	// Draw background -	if( mIsOpaque ) +	if (getRect().isValid())   	{ -		F32 alpha = getCurrentTransparency(); +		// Draw background +		if( mIsOpaque ) +		{ +			F32 alpha = getCurrentTransparency(); -		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -		gl_rect_2d(mInnerRect, mBackgroundColor.get() % alpha); -	} +			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +			gl_rect_2d(mInnerRect, mBackgroundColor.get() % alpha); +		} -	// Draw mScrolledViews and update scroll bars. -	// get a scissor region ready, and draw the scrolling view. The -	// scissor region ensures that we don't draw outside of the bounds -	// of the rectangle. -	if( mScrolledView ) -	{ -		updateScroll(); - -		// Draw the scrolled area. +		// Draw mScrolledViews and update scroll bars. +		// get a scissor region ready, and draw the scrolling view. The +		// scissor region ensures that we don't draw outside of the bounds +		// of the rectangle. +		if( mScrolledView )  		{ -			S32 visible_width = 0; -			S32 visible_height = 0; -			BOOL show_v_scrollbar = FALSE; -			BOOL show_h_scrollbar = FALSE; -			calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); - -			LLLocalClipRect clip(LLRect(mInnerRect.mLeft,  -					mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height, -					mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0), -					mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) -					)); -			drawChild(mScrolledView); -		} -	} - -	// Highlight border if a child of this container has keyboard focus -	if( mBorder->getVisible() ) -	{ -		mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus(this) ); -	} +			updateScroll(); -	// Draw all children except mScrolledView -	// Note: scrollbars have been adjusted by above drawing code -	for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin(); -		 child_iter != getChildList()->rend(); ++child_iter) -	{ -		LLView *viewp = *child_iter; -		if( sDebugRects ) -		{ -			sDepth++; +			// Draw the scrolled area. +			{ +				S32 visible_width = 0; +				S32 visible_height = 0; +				BOOL show_v_scrollbar = FALSE; +				BOOL show_h_scrollbar = FALSE; +				calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + +				LLLocalClipRect clip(LLRect(mInnerRect.mLeft,  +						mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height, +						mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0), +						mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) +						)); +				drawChild(mScrolledView); +			}  		} -		if( (viewp != mScrolledView) && viewp->getVisible() ) + +		// Highlight border if a child of this container has keyboard focus +		if( mBorder->getVisible() )  		{ -			drawChild(viewp); +			mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus(this) );  		} -		if( sDebugRects ) + +		// Draw all children except mScrolledView +		// Note: scrollbars have been adjusted by above drawing code +		for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin(); +			 child_iter != getChildList()->rend(); ++child_iter)  		{ -			sDepth--; +			LLView *viewp = *child_iter; +			if( sDebugRects ) +			{ +				sDepth++; +			} +			if( (viewp != mScrolledView) && viewp->getVisible() ) +			{ +				drawChild(viewp); +			} +			if( sDebugRects ) +			{ +				sDepth--; +			}  		}  	}  } // end draw diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 004681325f..e1ee0a5b14 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1093,6 +1093,11 @@ void LLView::drawChildren()  		{  			child_list_reverse_iter_t child = child_iter++;  			LLView *viewp = *child; +			 +			if (viewp == NULL) +			{ +				continue; +			}  			if (viewp->getVisible() && viewp->getRect().isValid())  			{ diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp index ae8b30b1ba..f5c463c961 100644 --- a/indra/llui/llwindowshade.cpp +++ b/indra/llui/llwindowshade.cpp @@ -160,7 +160,7 @@ void LLWindowShade::draw()  	notification_area->reshape(notification_area->getRect().getWidth(),   		llclamp(message_rect.getHeight() + 15,  -				llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT), +				llmax(mFormHeight, MIN_NOTIFICATION_AREA_HEIGHT),  				MAX_NOTIFICATION_AREA_HEIGHT));  	LLUICtrl::draw(); @@ -176,12 +176,12 @@ void LLWindowShade::draw()  	{  		hide();  	} -	else if (notification_area->getCollapseFactor() < 0.01f) +	else if (notification_area->getVisibleAmount() < 0.01f)  	{  		displayLatestNotification();  	} -	if (!notification_area->getVisible() && (notification_area->getCollapseFactor() < 0.001f)) +	if (!notification_area->getVisible() && (notification_area->getVisibleAmount() < 0.001f))  	{  		getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(false);  		setMouseOpaque(false); @@ -371,6 +371,11 @@ void LLWindowShade::setTextColor(LLColor4 color)  	getChild<LLTextBox>("notification_text")->setColor(color);  } +bool LLWindowShade::isShown() const +{ +	return getChildRef<LLLayoutPanel>("notification_area").getVisible(); +} +  void LLWindowShade::setCanClose(bool can_close)  {  	getChildView("close_panel")->setVisible(can_close); diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h index 1ae84028dd..6d753d1161 100644 --- a/indra/llui/llwindowshade.h +++ b/indra/llui/llwindowshade.h @@ -48,6 +48,9 @@ public:  	void show(LLNotificationPtr);  	/*virtual*/ void draw();  	void hide(); +	 +	bool isShown() const; +  	void setBackgroundImage(LLUIImage* image);  	void setTextColor(LLColor4 color);  	void setCanClose(bool can_close);  | 
