diff options
Diffstat (limited to 'indra')
52 files changed, 1066 insertions, 523 deletions
| diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index 6a1b48a08a..f6c4b69308 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -163,16 +163,6 @@ bool LLChatEntry::useLabel()      return !getLength() && !mLabel.empty();  } -void LLChatEntry::onFocusReceived() -{ - -} - -void LLChatEntry::onFocusLost() -{ - -} -  BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)  {  	BOOL handled = FALSE; diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h index 49c8d21450..a20a505ae1 100644 --- a/indra/llui/llchatentry.h +++ b/indra/llui/llchatentry.h @@ -62,8 +62,6 @@ public:  	virtual void	draw();  	virtual	void	onCommit(); -    /*virtual*/ void	onFocusReceived(); -    /*virtual*/ void	onFocusLost();  	void enableSingleLineMode(bool single_line_mode);  	boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 09e27a264a..d97569839a 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -507,22 +507,11 @@ LLFloater::~LLFloater()  {  	LLFloaterReg::removeInstance(mInstanceName, mKey); -//	delete mNotificationContext; -//	mNotificationContext = NULL; - -	//// am I not hosted by another floater? -	//if (mHostHandle.isDead()) -	//{ -	//	LLFloaterView* parent = (LLFloaterView*) getParent(); - -	//	if( parent ) -	//	{ -	//		parent->removeChild( this ); -	//	} -	//} - -	// Just in case we might still have focus here, release it. -	releaseFocus(); +	if( gFocusMgr.childHasKeyboardFocus(this)) +	{ +		// Just in case we might still have focus here, release it. +		releaseFocus(); +	}  	// This is important so that floaters with persistent rects (i.e., those  	// created with rect control rather than an LLRect) are restored in their @@ -2788,7 +2777,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out  	}  	// move window fully onscreen -	if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX )) +	if (floater->translateIntoRect( gFloaterView->getRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))  	{  		floater->clearSnapTarget();  	} @@ -3258,6 +3247,11 @@ bool LLFloater::isShown() const      return ! isMinimized() && isInVisibleChain();  } +bool LLFloater::isDetachedAndNotMinimized() +{ +	return !getHost() && !isMinimized(); +} +  /* static */  bool LLFloater::isShown(const LLFloater* floater)  { diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 4dba1e645f..26ac4a98ad 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -238,6 +238,7 @@ public:  	void			center();  	LLMultiFloater* getHost(); +	bool isDetachedAndNotMinimized();  	void			applyTitle();  	std::string		getCurrentTitle() const; diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 8aa1eb7cd5..cf449217f5 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -323,9 +323,11 @@ static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View");  void LLFolderView::filter( LLFolderViewFilter& filter )  { +    // Entry point of inventory filtering (CHUI-849)  	LLFastTimer t2(FTM_FILTER); -	filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); +    filter.resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32(mParentPanel->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100)); +    // Note: we filter the model, not the view  	getViewModelItem()->filter(filter);  } @@ -661,7 +663,7 @@ void LLFolderView::draw()  		// get preferable text height...  		S32 pixel_height = mStatusTextBox->getTextPixelHeight(); -		bool height_changed = local_rect.getHeight() != pixel_height; +		bool height_changed = (local_rect.getHeight() < pixel_height);  		if (height_changed)  		{  			// ... if it does not match current height, lets rearrange current view. @@ -1601,15 +1603,17 @@ void LLFolderView::update()  	{  		mNeedsAutoSelect = TRUE;  	} -	// filter to determine visibility before arranging +     +	// Filter to determine visibility before arranging  	filter(getFolderViewModel()->getFilter()); -	// Clear the modified setting on the filter only if the filter count is non-zero after running the filter process -	// Note: if the filter count is zero, then the filter most likely halted before completing the entire set of items -	if (getFolderViewModel()->getFilter().isModified() && (getFolderViewModel()->getFilter().getFilterCount() > 0)) +     +	// Clear the modified setting on the filter only if the filter finished after running the filter process +	// Note: if the filter count has timed out, that means the filter halted before completing the entire set of items +    if (getFolderViewModel()->getFilter().isModified() && (!getFolderViewModel()->getFilter().isTimedOut()))  	{  		getFolderViewModel()->getFilter().clearModified();  	} - +      	// automatically show matching items, and select first one if we had a selection  	if (mNeedsAutoSelect)  	{ @@ -1649,11 +1653,13 @@ void LLFolderView::update()    BOOL is_visible = isInVisibleChain(); -  //Puts folders/items in proper positions -  if ( is_visible ) +  // Puts folders/items in proper positions +  // arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849) +  // It also handles the open/close folder animation +  if (is_visible)    {      sanitizeSelection(); -    if( needsArrange() ) +    if (needsArrange())      {        S32 height = 0;        S32 width = 0; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index fdb4108afb..6c147ccc12 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -274,6 +274,7 @@ void LLFolderViewItem::refresh()  	}  	mLabelWidthDirty = true; +    // Dirty the filter flag of the model from the view (CHUI-849)  	vmi.dirtyFilter();  } @@ -943,11 +944,17 @@ void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)  static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); -// Finds width and height of this object and its children. Also -// makes sure that this view and its children are the right size. +// Make everything right and in the right place ready for drawing (CHUI-849) +// * Sort everything correctly if necessary +// * Turn widgets visible/invisible according to their model filtering state +// * Takes animation state into account for opening/closing of folders (this makes widgets visible/invisible) +// * Reposition visible widgets so that they line up correctly with no gap +// * Compute the width and height of the current folder and its children +// * Makes sure that this view and its children are the right size  S32 LLFolderViewFolder::arrange( S32* width, S32* height )  { -	// sort before laying out contents +	// Sort before laying out contents +    // Note that we sort from the root (CHUI-849)  	getRoot()->getFolderViewModel()->sort(this);  	LLFastTimer t2(FTM_ARRANGE); @@ -1613,16 +1620,13 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)  }  void LLFolderViewFolder::requestArrange() -{  -	if ( mLastArrangeGeneration != -1) -	{ -		mLastArrangeGeneration = -1;  -		// flag all items up to root -		if (mParentFolder) -		{ -			mParentFolder->requestArrange(); -		} -	} +{ +    mLastArrangeGeneration = -1; +    // flag all items up to root +    if (mParentFolder) +    { +        mParentFolder->requestArrange(); +    }  }  void LLFolderViewFolder::toggleOpen() diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index ca31931e19..a9b0201236 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -316,7 +316,6 @@ protected:  	F32			mAutoOpenCountdown;  	S32			mLastArrangeGeneration;  	S32			mLastCalculatedWidth; -	S32			mMostFilteredDescendantGeneration;  	bool		mNeedsSort;  public: diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index 3593804554..3363dc5316 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -48,7 +48,7 @@ std::string LLFolderViewModelCommon::getStatusText()  void LLFolderViewModelCommon::filter()  { -	getFilter().setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); +    getFilter().resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100));  	mFolderView->getViewModelItem()->filter(getFilter());  } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 1b61212c0e..b1bcc8bbb4 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -87,12 +87,11 @@ public:  	virtual void 				setModified(EFilterModified behavior = FILTER_RESTART) = 0;  	// +-------------------------------------------------------------------+ -	// + Count +	// + Time  	// +-------------------------------------------------------------------+ -	virtual void 				setFilterCount(S32 count) = 0; -	virtual S32 				getFilterCount() const = 0; -	virtual void 				decrementFilterCount() = 0; - +	virtual void 				resetTime(S32 timeout) = 0; +    virtual bool                isTimedOut() = 0; +      	// +-------------------------------------------------------------------+  	// + Default  	// +-------------------------------------------------------------------+ @@ -308,26 +307,28 @@ public:  	virtual bool potentiallyVisible()  	{  		return passedFilter() // we've passed the filter -			|| getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration() // or we don't know yet +			|| (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet  			|| descendantsPassedFilter();  	}  	virtual bool passedFilter(S32 filter_generation = -1)   	{  -		if (filter_generation < 0)  +		if (filter_generation < 0) +        {  			filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); - -		bool passed_folder_filter = mPassedFolderFilter && mLastFolderFilterGeneration >= filter_generation; -		bool passed_filter = mPassedFilter && mLastFilterGeneration >= filter_generation; -		return passed_folder_filter -				&& (descendantsPassedFilter(filter_generation) -					|| passed_filter); +        } +		bool passed_folder_filter = mPassedFolderFilter && (mLastFolderFilterGeneration >= filter_generation); +		bool passed_filter = mPassedFilter && (mLastFilterGeneration >= filter_generation); +		return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation));  	}  	virtual bool descendantsPassedFilter(S32 filter_generation = -1)  	{  -		if (filter_generation < 0) filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); -		return mMostFilteredDescendantGeneration >= filter_generation;  +		if (filter_generation < 0) +        { +            filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); +        } +		return mMostFilteredDescendantGeneration >= filter_generation;  	} diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index e33ac1d5c2..c89c0203b4 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -214,8 +214,15 @@ LLLayoutStack::Params::Params()  	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)) -{} +	border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)), +	show_drag_handle("show_drag_handle", false), +	drag_handle_first_indent("drag_handle_first_indent", 0), +	drag_handle_second_indent("drag_handle_second_indent", 0), +	drag_handle_thickness("drag_handle_thickness", 5), +	drag_handle_shift("drag_handle_shift", 2) +{ +	addSynonym(border_size, "drag_handle_gap"); +}  LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)   :	LLView(p), @@ -227,8 +234,14 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)  	mClip(p.clip),  	mOpenTimeConstant(p.open_time_constant),  	mCloseTimeConstant(p.close_time_constant), -	mResizeBarOverlap(p.resize_bar_overlap) -{} +	mResizeBarOverlap(p.resize_bar_overlap), +	mShowDragHandle(p.show_drag_handle), +	mDragHandleFirstIndent(p.drag_handle_first_indent), +	mDragHandleSecondIndent(p.drag_handle_second_indent), +	mDragHandleThickness(p.drag_handle_thickness), +	mDragHandleShift(p.drag_handle_shift) +{ +}  LLLayoutStack::~LLLayoutStack()  { @@ -262,6 +275,26 @@ void LLLayoutStack::draw()  			drawChild(panelp, 0, 0, !clip_rect.isEmpty());  		}  	} + +	const LLView::child_list_t * child_listp = getChildList(); +	BOOST_FOREACH(LLView * childp, * child_listp) +	{ +		LLResizeBar * resize_barp = dynamic_cast<LLResizeBar*>(childp); +		if (resize_barp && resize_barp->isShowDragHandle() && resize_barp->getVisible() && resize_barp->getRect().isValid()) +		{ +			LLRect screen_rect = resize_barp->calcScreenRect(); +			if (LLUI::getRootView()->getLocalRect().overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect)) +			{ +				LLUI::pushMatrix(); +				{ +					const LLRect& rb_rect(resize_barp->getRect()); +					LLUI::translate(rb_rect.mLeft, rb_rect.mBottom); +					resize_barp->draw(); +				} +				LLUI::popMatrix(); +			} +		} +	}  }  void LLLayoutStack::removeChild(LLView* view) @@ -390,7 +423,6 @@ void LLLayoutStack::updateLayout()  	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) @@ -407,27 +439,61 @@ void LLLayoutStack::updateLayout()  										getRect().getWidth(),  										llround(panel_dim));  		} -		panelp->setIgnoreReshape(true); -		panelp->setShape(panel_rect); -		panelp->setIgnoreReshape(false);  		LLRect resize_bar_rect(panel_rect); - +		LLResizeBar * resize_barp = panelp->getResizeBar(); +		bool show_drag_handle = resize_barp->isShowDragHandle();  		F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount(); +		F32 panel_visible_dim = panelp->getVisibleDim(); +		S32 panel_spacing_round = (S32)(llround(panel_spacing)); +  		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; + +			if (show_drag_handle && panel_spacing_round > mDragHandleThickness) +			{ +				resize_bar_rect.mLeft = panel_rect.mRight + mDragHandleShift; +				resize_bar_rect.mRight = resize_bar_rect.mLeft + mDragHandleThickness; +			} +			else +			{ +				resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap; +				resize_bar_rect.mRight = panel_rect.mRight + panel_spacing_round + mResizeBarOverlap; +			} + +			if (show_drag_handle) +			{ +				resize_bar_rect.mBottom += mDragHandleSecondIndent; +				resize_bar_rect.mTop -= mDragHandleFirstIndent; +			} +  		}  		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; + +			if (show_drag_handle && panel_spacing_round > mDragHandleThickness) +			{ +				resize_bar_rect.mTop = panel_rect.mBottom - mDragHandleShift; +				resize_bar_rect.mBottom = resize_bar_rect.mTop - mDragHandleThickness; +			} +			else +			{ +				resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap; +				resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing_round - mResizeBarOverlap; +			} + +			if (show_drag_handle) +			{ +				resize_bar_rect.mLeft += mDragHandleFirstIndent; +				resize_bar_rect.mRight -= mDragHandleSecondIndent; +			}  		} + +		panelp->setIgnoreReshape(true); +		panelp->setShape(panel_rect); +		panelp->setIgnoreReshape(false);  		panelp->mResizeBar->setShape(resize_bar_rect);  	} @@ -475,14 +541,13 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)  	{  		if (lp->mResizeBar == NULL)  		{ -			LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; -  			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.side((mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM);  			resize_params.snapping_enabled(false); +			resize_params.show_drag_handle(mShowDragHandle);  			LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);  			lp->mResizeBar = resize_bar;  			LLView::addChild(resize_bar, 0); @@ -864,3 +929,4 @@ void LLLayoutStack::updateResizeBarLimits()  		previous_visible_panelp = visible_panelp;  	}  } + diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 02c664f1a0..b570974bd6 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -62,6 +62,11 @@ public:  		Optional<F32>			open_time_constant,  								close_time_constant;  		Optional<S32>			resize_bar_overlap; +		Optional<bool>			show_drag_handle; +		Optional<S32>			drag_handle_first_indent; +		Optional<S32>			drag_handle_second_indent; +		Optional<S32>			drag_handle_thickness; +		Optional<S32>			drag_handle_shift;  		Params();  	}; @@ -126,6 +131,11 @@ private:  	F32  mCloseTimeConstant;  	bool mNeedsLayout;  	S32  mResizeBarOverlap; +	bool mShowDragHandle; +	S32  mDragHandleFirstIndent; +	S32  mDragHandleSecondIndent; +	S32  mDragHandleThickness; +	S32  mDragHandleShift;  }; // end class LLLayoutStack diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index f7bf39c897..f854e1785d 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3146,6 +3146,13 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)  	const S32 CURSOR_HEIGHT = 22;		// Approximate "normal" cursor size  	const S32 CURSOR_WIDTH = 12; +	if (menu->getChildList()->empty()) +	{ +		return; +	} + +	menu->setVisible( TRUE ); +  	//Do not show menu if all menu items are disabled  	BOOL item_enabled = false;  	for (LLView::child_list_t::const_iterator itor = menu->getChildList()->begin(); @@ -3156,8 +3163,9 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)  		item_enabled = item_enabled || menu_item->getEnabled();  	} -	if(menu->getChildList()->empty() || !item_enabled) +	if(!item_enabled)  	{ +		menu->setVisible( FALSE );  		return;  	} @@ -3173,8 +3181,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)  		menu->mFirstVisibleItem = NULL;  	} -	menu->setVisible( TRUE ); -  	// Fix menu rect if needed.  	menu->needsArrange();  	menu->arrangeAndClear(); diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index 15e56cbfe5..e67b22c977 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -28,14 +28,53 @@  #include "llresizebar.h" +#include "lllocalcliprect.h"  #include "llmath.h"  #include "llui.h"  #include "llmenugl.h"  #include "llfocusmgr.h"  #include "llwindow.h" +class LLImagePanel : public LLPanel +{ +public: +	struct Params :	public LLInitParam::Block<Params, LLPanel::Params> +	{ +		Optional<bool> horizontal; +		Params() : horizontal("horizontal", false) {} +	}; +	LLImagePanel(const Params& p) : LLPanel(p), mHorizontal(p.horizontal) {} +	virtual ~LLImagePanel() {} + +	void draw() +	{ +		const LLRect& parent_rect = getParent()->getRect(); +		const LLRect& rect = getRect(); +		LLRect clip_rect( -rect.mLeft, parent_rect.getHeight() - rect.mBottom - 2 +						 , parent_rect.getWidth() - rect.mLeft - (mHorizontal ? 2 : 0), -rect.mBottom); +		LLLocalClipRect clip(clip_rect); +		LLPanel::draw(); +	} + +private: +	bool mHorizontal; +}; + +static LLDefaultChildRegistry::Register<LLImagePanel> t1("resize_bar_image_panel"); + +LLResizeBar::Params::Params() +:	max_size("max_size", S32_MAX), +	snapping_enabled("snapping_enabled", true), +	resizing_view("resizing_view"), +	side("side"), +	allow_double_click_snapping("allow_double_click_snapping", true), +	show_drag_handle("show_drag_handle", false) +{ +	name = "resize_bar"; +} +  LLResizeBar::LLResizeBar(const LLResizeBar::Params& p) -:	LLView(p), +:	LLPanel(p),  	mDragLastScreenX( 0 ),  	mDragLastScreenY( 0 ),  	mLastMouseScreenX( 0 ), @@ -46,7 +85,9 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)  	mSnappingEnabled(p.snapping_enabled),  	mAllowDoubleClickSnapping(p.allow_double_click_snapping),  	mResizingView(p.resizing_view), -	mResizeListener(NULL) +	mResizeListener(NULL), +	mShowDragHandle(p.show_drag_handle), +	mImagePanel(NULL)  {  	setFollowsNone();  	// set up some generically good follow code. @@ -75,8 +116,37 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)  	default:  		break;  	} + +	if (mShowDragHandle) +	{ +		LLViewBorder::Params border_params; +		border_params.border_thickness = 1; +		border_params.highlight_light_color = LLUIColorTable::instance().getColor("ResizebarBorderLight"); +		border_params.shadow_dark_color = LLUIColorTable::instance().getColor("ResizebarBorderDark"); + +		addBorder(border_params); +		setBorderVisible(TRUE); + +		LLImagePanel::Params image_panel; +		mDragHandleImage = LLUI::getUIImage(LLResizeBar::RIGHT == mSide ? "Vertical Drag Handle" : "Horizontal Drag Handle"); +		image_panel.bg_alpha_image = mDragHandleImage; +		image_panel.background_visible = true; +		image_panel.horizontal = (LLResizeBar::BOTTOM == mSide); +		mImagePanel = LLUICtrlFactory::create<LLImagePanel>(image_panel); +		setImagePanel(mImagePanel); +	}  } +BOOL LLResizeBar::postBuild() +{ +	if (mShowDragHandle) +	{ +		setBackgroundVisible(TRUE); +		setTransparentColor(LLUIColorTable::instance().getColor("ResizebarBody")); +	} + +	return LLPanel::postBuild(); +}  BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask)  { @@ -342,3 +412,39 @@ BOOL LLResizeBar::handleDoubleClick(S32 x, S32 y, MASK mask)  	return TRUE;  } +void LLResizeBar::setImagePanel(LLPanel * panelp) +{ +	const LLView::child_list_t * children = getChildList(); +	if (getChildCount() == 2) +	{ +		LLPanel * image_panelp = dynamic_cast<LLPanel*>(children->back()); +		if (image_panelp) +		{ +			removeChild(image_panelp); +			delete image_panelp; +		} +	} + +	addChild(panelp); +	sendChildToBack(panelp); +} + +LLPanel * LLResizeBar::getImagePanel() const +{ +	return getChildCount() > 0 ? (LLPanel *)getChildList()->back() : NULL; +} + +void LLResizeBar::draw() +{ +	if (mShowDragHandle) +	{ +		S32 image_width = mDragHandleImage->getTextureWidth(); +		S32 image_height = mDragHandleImage->getTextureHeight(); +		const LLRect& panel_rect = getRect(); +		S32 image_left = (panel_rect.getWidth() - image_width) / 2 - 1; +		S32 image_bottom = (panel_rect.getHeight() - image_height) / 2; +		mImagePanel->setRect(LLRect(image_left, image_bottom + image_height, image_left + image_width, image_bottom)); +	} + +	LLPanel::draw(); +} diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 8190a95a71..bcf8ea0b40 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -27,15 +27,14 @@  #ifndef LL_RESIZEBAR_H  #define LL_RESIZEBAR_H -#include "llview.h" -#include "llcoord.h" +#include "llpanel.h" -class LLResizeBar : public LLView +class LLResizeBar : public LLPanel  {  public:  	enum Side { LEFT, TOP, RIGHT, BOTTOM }; -	struct Params : public LLInitParam::Block<Params, LLView::Params> +	struct Params : public LLInitParam::Block<Params, LLPanel::Params>  	{  		Mandatory<LLView*> resizing_view;  		Mandatory<Side>	side; @@ -44,24 +43,19 @@ public:  		Optional<S32>	max_size;  		Optional<bool>	snapping_enabled;  		Optional<bool>	allow_double_click_snapping; +		Optional<bool>	show_drag_handle; -		Params() -		:	max_size("max_size", S32_MAX), -			snapping_enabled("snapping_enabled", true), -			resizing_view("resizing_view"), -			side("side"), -			allow_double_click_snapping("allow_double_click_snapping", true) -		{ -			name = "resize_bar"; -		} +		Params();  	};  protected:  	LLResizeBar(const LLResizeBar::Params& p);  	friend class LLUICtrlFactory; + +	/*virtual*/ BOOL postBuild();  public: -//	virtual void	draw();  No appearance +	virtual void	draw();  	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask); @@ -72,20 +66,26 @@ public:  	void			setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; }  	bool			canResize() { return getEnabled() && mMaxSize > mMinSize; }  	void            setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;} +	BOOL			isShowDragHandle() const { return mShowDragHandle; } +	void			setImagePanel(LLPanel * panelp); +	LLPanel *		getImagePanel() const;  private: -	S32				mDragLastScreenX; -	S32				mDragLastScreenY; -	S32				mLastMouseScreenX; -	S32				mLastMouseScreenY; -	LLCoordGL		mLastMouseDir; -	S32				mMinSize; -	S32				mMaxSize; -	const Side		mSide; -	BOOL			mSnappingEnabled; -	BOOL			mAllowDoubleClickSnapping; -	LLView*			mResizingView; -	boost::function<void(void*)>  mResizeListener; +	S32								mDragLastScreenX; +	S32								mDragLastScreenY; +	S32								mLastMouseScreenX; +	S32								mLastMouseScreenY; +	LLCoordGL						mLastMouseDir; +	S32								mMinSize; +	S32								mMaxSize; +	const Side						mSide; +	BOOL							mSnappingEnabled; +	BOOL							mAllowDoubleClickSnapping; +	BOOL							mShowDragHandle; +	LLView*							mResizingView; +	boost::function<void(void*)>	mResizeListener; +	LLPointer<LLUIImage>			mDragHandleImage; +	LLPanel *						mImagePanel;  };  #endif  // LL_RESIZEBAR_H diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index e70992129a..391e6fd005 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -653,6 +653,10 @@ void LLTextBase::drawText()  			mSpellCheckEnd = end;  		}  	} +	else +	{ +		mMisspellRanges.clear(); +	}  	LLTextSegmentPtr cur_segment = *seg_iter; @@ -2602,21 +2606,18 @@ void LLTextBase::setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool  void LLTextBase::changeLine( S32 delta )  {  	S32 line = getLineNumFromDocIndex(mCursorPos); - -	S32 new_line = line; -	if( (delta < 0) && (line > 0 ) ) -	{ -		new_line = line - 1; -	} -	else if( (delta > 0) && (line < (getLineCount() - 1)) ) -	{ -		new_line = line + 1; -	} - -	LLRect visible_region = getVisibleDocumentRect(); - -	S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE); -	setCursorPos(new_cursor_pos, true); +	S32 max_line_nb = getLineCount() - 1; +	max_line_nb = (max_line_nb < 0 ? 0 : max_line_nb); +     +	S32 new_line = llclamp(line + delta, 0, max_line_nb); + +    if (new_line != line) +    { +        LLRect visible_region = getVisibleDocumentRect(); +        S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, +                                                       mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE); +        setCursorPos(new_cursor_pos, true); +    }  }  bool LLTextBase::scrolledToStart() diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 43c0090993..ca9410de2e 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -159,9 +159,8 @@ LLWinImm LLWinImm::sTheInstance;  LLWinImm::LLWinImm() : mHImmDll(NULL)  {  	// Check system metrics  -	if ( !GetSystemMetrics( SM_DBCSENABLED ) ) +	if ( !GetSystemMetrics( SM_IMMENABLED ) )  		return; -	  	mHImmDll = LoadLibraryA("Imm32");  	if (mHImmDll != NULL) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f66d8fca5b..03135caf93 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3446,16 +3446,27 @@          <key>Value</key>              <real>10.0</real>          </map> -    <key>FilterItemsPerFrame</key> +    <key>FilterItemsMaxTimePerFrameVisible</key>      <map> -      <key>Comment</key> -      <string>Maximum number of inventory items to match against search filter every frame (lower to increase framerate while searching, higher to improve search speed)</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>S32</string> -      <key>Value</key> -      <integer>500</integer> +        <key>Comment</key> +        <string>Max time devoted to items filtering per frame for visible inventory listings (in milliseconds)</string> +        <key>Persist</key> +        <integer>1</integer> +        <key>Type</key> +        <string>S32</string> +        <key>Value</key> +        <integer>10</integer> +    </map> +    <key>FilterItemsMaxTimePerFrameUnvisible</key> +    <map> +        <key>Comment</key> +        <string>Max time devoted to items filtering per frame for non visible inventory listings (in milliseconds)</string> +        <key>Persist</key> +        <integer>1</integer> +        <key>Type</key> +        <string>S32</string> +        <key>Value</key> +        <integer>1</integer>      </map>      <key>FindLandArea</key>      <map> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 8c42defa73..d16945070a 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -46,6 +46,7 @@  #include "llenvmanager.h"  #include "llfirstuse.h"  #include "llfloatercamera.h" +#include "llfloaterimcontainer.h"  #include "llfloaterreg.h"  #include "llfloatertools.h"  #include "llgroupactions.h" @@ -91,6 +92,7 @@  #include "llworld.h"  #include "llworldmap.h"  #include "stringize.h" +#include "boost/foreach.hpp"  using namespace LLAvatarAppearanceDefines; @@ -2037,7 +2039,16 @@ void LLAgent::endAnimationUpdateUI()  			{  				skip_list.insert(LLFloaterReg::findInstance("mini_map"));  			} -		 + +			LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); +			LLFloaterIMContainer::floater_list_t conversations; +			im_box->getDetachedConversationFloaters(conversations); +			BOOST_FOREACH(LLFloater* conversation, conversations) +			{ +				llinfos << "skip_list.insert(session_floater): " << conversation->getTitle() << llendl; +				skip_list.insert(conversation); +			} +  			gFloaterView->popVisibleAll(skip_list);  #endif  			mViewsPushed = FALSE; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index c74ce24872..6e95df8383 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -386,6 +386,10 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags)          addVoiceOptions(items);          items.push_back(std::string("chat_history"));      } +    else if(this->getType() == CONV_SESSION_NEARBY) +    { +        items.push_back(std::string("chat_history")); +    }      hide_context_entries(menu, items, disabled_items);  } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 8766585049..d8cdcdfc97 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -252,11 +252,10 @@ public:  	const std::string& 	getName() const { return mEmpty; }  	const std::string& 	getFilterText() { return mEmpty; }  	void 				setModified(EFilterModified behavior = FILTER_RESTART) { } -		 -	void 				setFilterCount(S32 count) { } -	S32 				getFilterCount() const { return 0; } -	void 				decrementFilterCount() { } -		 + +  	void 				resetTime(S32 timeout) { } +    bool                isTimedOut() { return false; } +     	bool 				isDefault() const { return true; }  	bool 				isNotDefault() const { return false; }  	void 				markDefault() { } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index b6c53e5e30..42104ea20a 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -118,6 +118,13 @@ void LLConversationViewSession::setFlashState(bool flash_state)  	mFlashTimer->stopFlashing();  } +void LLConversationViewSession::setHighlightState(bool hihglight_state) +{ +	mFlashStateOn = hihglight_state; +	mFlashStarted = true; +	mFlashTimer->stopFlashing(); +} +  void LLConversationViewSession::startFlashing()  {  	if (isInVisibleChain() && mFlashStateOn && !mFlashStarted) @@ -340,16 +347,20 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible)  {  	// Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized  	// Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here -	LLFolderViewModelItem* item = mViewModelItem; -	LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID(); -	LLFloater* session_floater = LLFloaterIMSessionTab::getConversation(session_uuid); -	 -	if (session_floater && !session_floater->getHost() && !session_floater->isMinimized()) +	LLFloater* session_floater = getSessionFloater(); +	if (session_floater && session_floater->isDetachedAndNotMinimized())  	{  		session_floater->setVisible(visible);  	}  } +LLFloater* LLConversationViewSession::getSessionFloater() +{ +	LLFolderViewModelItem* item = mViewModelItem; +	LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID(); +	return LLFloaterIMSessionTab::getConversation(session_uuid); +} +  LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id)  {  	// This is *not* a general tree parsing algorithm. We search only in the mItems list diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 3eb2e63792..879d496dc7 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -86,6 +86,9 @@ public:  	virtual void refresh();  	/*virtual*/ void setFlashState(bool flash_state); +	void setHighlightState(bool hihglight_state); + +	LLFloater* getSessionFloater();  private: diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 82affcf068..71bc4f15d2 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -115,7 +115,8 @@ void LLDoNotDisturbNotificationStorage::saveNotifications()  	{  		LLNotificationPtr notificationPtr = historyIter->second; -		if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired()) +		if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && +			!notificationPtr->isExpired() && !notificationPtr->isPersistent())  		{  			data.append(notificationPtr->asLLSD(true));  		} @@ -210,12 +211,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()  	} -    if(imToastExists) -    { -        LLFloaterReg::showInstance("im_container"); -    } - -	if(group_ad_hoc_toast_exists) +    bool isConversationLoggingAllowed = gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0; +	if(group_ad_hoc_toast_exists && isConversationLoggingAllowed)  	{  		LLFloaterReg::showInstance("conversation");  	} @@ -266,11 +263,6 @@ void LLDoNotDisturbNotificationStorage::updateNotifications()          }      } -    if(imToastExists) -    {    -        LLFloaterReg::showInstance("im_container"); -    } -      if(imToastExists || offerExists)      {          make_ui_sound("UISndNewIncomingIMSession"); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 58817485fb..b88888da3b 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -54,6 +54,7 @@  #include "llworld.h"  #include "llsdserialize.h"  #include "llviewerobjectlist.h" +#include "boost/foreach.hpp"  //  // LLFloaterIMContainer @@ -63,7 +64,8 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param  	mExpandCollapseBtn(NULL),  	mConversationsRoot(NULL),  	mConversationsEventStream("ConversationsEvents"), -	mInitialized(false) +	mInitialized(false), +	mIsFirstLaunch(true)  {      mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));  	mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction,  this, _2)); @@ -204,6 +206,7 @@ BOOL LLFloaterIMContainer::postBuild()  	// a scroller for folder view  	LLRect scroller_view_rect = mConversationsListPanel->getRect();  	scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); +	scroller_view_rect.mBottom += getChild<LLLayoutStack>("conversations_pane_buttons_stack")->getRect().getHeight();  	LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>());  	scroller_params.rect(scroller_view_rect); @@ -221,7 +224,8 @@ BOOL LLFloaterIMContainer::postBuild()  	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this));  	mStubCollapseBtn = getChild<LLButton>("stub_collapse_btn");  	mStubCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onStubCollapseButtonClicked, this)); -	getChild<LLButton>("speak_btn")->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this)); +    mSpeakBtn = getChild<LLButton>("speak_btn"); +	mSpeakBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this));  	childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this)); @@ -659,10 +663,32 @@ void LLFloaterIMContainer::setVisible(BOOL visible)  	LLMultiFloater::setVisible(visible);  } +void LLFloaterIMContainer::getDetachedConversationFloaters(floater_list_t& floaters) +{ +	typedef conversations_widgets_map::value_type conv_pair; +	BOOST_FOREACH(conv_pair item, mConversationsWidgets) +	{ +		LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(item.second); +		if (widget) +		{ +			LLFloater* session_floater = widget->getSessionFloater(); +			if (session_floater && session_floater->isDetachedAndNotMinimized()) +			{ +				floaters.push_back(session_floater); +			} +		} +	} +} +  void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)  {  	LLMultiFloater::setVisibleAndFrontmost(take_focus, key);      selectConversationPair(getSelectedSession(), false, take_focus); +	if (mInitialized && mIsFirstLaunch) +	{ +		collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); +		mIsFirstLaunch = false; +	}  }  void LLFloaterIMContainer::updateResizeLimits() @@ -779,13 +805,6 @@ void LLFloaterIMContainer::reshapeFloaterAndSetResizeLimits(bool collapse, S32 d  	setCanMinimize(at_least_one_panel_is_expanded);      assignResizeLimits(); - -    // force set correct size for the title after show/hide minimize button -	LLRect cur_rect = getRect(); -	LLRect force_rect = cur_rect; -	force_rect.mRight = cur_rect.mRight + 1; -    setRect(force_rect); -    setRect(cur_rect);  }  void LLFloaterIMContainer::assignResizeLimits() @@ -793,15 +812,12 @@ void LLFloaterIMContainer::assignResizeLimits()  	bool is_conv_pane_expanded = !mConversationsPane->isCollapsed();  	bool is_msg_pane_expanded = !mMessagesPane->isCollapsed(); -	// With two panels visible number of borders is three, because the borders -	// between the panels are merged into one -    S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3); -    S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH; -	S32 conv_pane_target_width = is_conv_pane_expanded? -			(is_msg_pane_expanded? -					mConversationsPane->getRect().getWidth() -					: mConversationsPane->getExpandedMinDim()) -			: mConversationsPane->getMinDim(); +    S32 summary_width_of_visible_borders = (is_msg_pane_expanded ? mConversationsStack->getPanelSpacing() : 0) + 1; + +	S32 conv_pane_target_width = is_conv_pane_expanded +		? ( is_msg_pane_expanded?mConversationsPane->getRect().getWidth():mConversationsPane->getExpandedMinDim() ) +		: mConversationsPane->getMinDim(); +  	S32 msg_pane_min_width  = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0;  	S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders; @@ -1143,7 +1159,7 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,          }          else if("chat_history" == command)          { -			if (selectedIDS.size() > 0) +        	if (selectedIDS.size() > 0)  			{  				LLAvatarActions::viewChatHistory(selectedIDS.front());  			} @@ -1156,6 +1172,17 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,          	}          }      } +    //if there is no LLFloaterIMSession* instance for selected conversation it might be Nearby chat +    else +    { +    	if(conversationItem->getType() == LLConversationItem::CONV_SESSION_NEARBY) +    	{ +    		if("chat_history" == command) +    	    { +    	      	LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true); +    	    } +    	} +    }  }  void LLFloaterIMContainer::doToSelected(const LLSD& userdata) @@ -1211,7 +1238,19 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)  	//Enable Chat history item for ad-hoc and group conversations  	if ("can_chat_history" == item && uuids.size() > 0)  	{ -		return LLLogChat::isTranscriptExist(uuids.front()); +		//Disable menu item if selected participant is user agent +		if(uuids.front() != gAgentID) +		{ +			if (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_NEARBY) +			{ +				return LLLogChat::isNearbyTranscriptExist(); +			} +			else +			{ +				bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP); +				return LLLogChat::isTranscriptExist(uuids.front(),is_group); +			} +		}  	}  	// If nothing is selected(and selected item is not group chat), everything needs to be disabled @@ -1904,7 +1943,6 @@ void LLFloaterIMContainer::reSelectConversation()  void LLFloaterIMContainer::updateSpeakBtnState()  { -	LLButton* mSpeakBtn = getChild<LLButton>("speak_btn");  	mSpeakBtn->setToggleState(LLVoiceClient::getInstance()->getUserPTTState());  	mSpeakBtn->setEnabled(LLAgent::isActionAllowed("speak"));  } @@ -1925,6 +1963,17 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id,  	}  } +void LLFloaterIMContainer::highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted) +{ +	//Finds the conversation line item to highlight using the session_id +	LLConversationViewSession * widget = dynamic_cast<LLConversationViewSession *>(get_ptr_in_map(mConversationsWidgets,session_id)); + +	if (widget) +	{ +		widget->setHighlightState(is_highlighted); +	} +} +  bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget)  {  	llassert(conversation_item_widget != NULL); @@ -1940,23 +1989,28 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve  BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask )  { +	BOOL handled = FALSE; +  	if(mask == MASK_ALT)  	{  		if (KEY_RETURN == key )  		{  			expandConversation(); +			handled = TRUE;  		}  		if ((KEY_DOWN == key ) || (KEY_RIGHT == key))  		{  			selectNextorPreviousConversation(true); +			handled = TRUE;  		}  		if ((KEY_UP == key) || (KEY_LEFT == key))  		{  			selectNextorPreviousConversation(false); +			handled = TRUE;  		}  	} -	return TRUE; +	return handled;  }  bool LLFloaterIMContainer::selectAdjacentConversation(bool focus_selected) @@ -2013,7 +2067,9 @@ void LLFloaterIMContainer::expandConversation()  	}  } -void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) +// For conversations, closeFloater() (linked to Ctrl-W) does not actually close the floater but the active conversation. +// This is intentional so it doesn't confuse the user. onClickCloseBtn() closes the whole floater. +void LLFloaterIMContainer::onClickCloseBtn()  {  	// Always unminimize before trying to close.  	// Most of the time the user will never see this state. @@ -2022,7 +2078,31 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)  		LLMultiFloater::setMinimized(FALSE);  	} -	LLFloater::closeFloater(app_quitting); +	LLFloater::closeFloater(); +} + +void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) +{ +	// Check for currently active session +	LLUUID session_id = getSelectedSession(); +	// If current session is Nearby Chat or there is only one session remaining, close the floater +	if (mConversationsItems.size() == 1 || session_id == LLUUID() || app_quitting) +	{ +		onClickCloseBtn(); +	} + +	// Otherwise, close current conversation +	LLFloaterIMSessionTab* active_conversation = LLFloaterIMSessionTab::getConversation(session_id); +	if (active_conversation) +	{ +		active_conversation->closeFloater(); +	} +} + +void LLFloaterIMContainer::handleReshape(const LLRect& rect, bool by_user) +{ +	LLMultiFloater::handleReshape(rect, by_user); +	storeRectControl();  }  // EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index e39d20ec35..74c3640bad 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -63,6 +63,8 @@ public:  	/*virtual*/ void setVisible(BOOL visible);  	/*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());  	/*virtual*/ void updateResizeLimits(); +	/*virtual*/ void handleReshape(const LLRect& rect, bool by_user); +  	void onCloseFloater(LLUUID& id);  	/*virtual*/ void addFloater(LLFloater* floaterp,  @@ -130,6 +132,7 @@ private:  	void onStubCollapseButtonClicked();  	void processParticipantsStyleUpdate();  	void onSpeakButtonClicked(); +	/*virtual*/ void onClickCloseBtn();  	void collapseConversationsPane(bool collapse, bool save_is_allowed=true); @@ -169,6 +172,7 @@ private:  	LLButton* mExpandCollapseBtn;  	LLButton* mStubCollapseBtn; +    LLButton* mSpeakBtn;  	LLPanel* mStubPanel;  	LLTextBox* mStubTextBox;  	LLLayoutPanel* mMessagesPane; @@ -176,6 +180,7 @@ private:  	LLLayoutStack* mConversationsStack;  	bool mInitialized; +	bool mIsFirstLaunch;  	LLUUID mSelectedSession;  	std::string mGeneralTitle; @@ -190,9 +195,12 @@ public:  	void updateSpeakBtnState();  	static bool isConversationLoggingAllowed();  	void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); +	void highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted);  	bool isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget);  	boost::signals2::connection mMicroChangedSignal;  	S32 getConversationListItemSize() { return mConversationsWidgets.size(); } +	typedef std::list<LLFloater*> floater_list_t; +	void getDetachedConversationFloaters(floater_list_t& floaters);  private:  	LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 49f36a2f32..7e472466ed 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -568,7 +568,10 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )  			if (0 == channel)  			{  				// discard returned "found" boolean -				LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); +				if(!LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text)) +				{ +					utf8_revised_text = utf8text; +				}  			}  			else  			{ diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 8ec85e1160..848d5c34d2 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -442,8 +442,11 @@ void LLFloaterIMSession::addSessionParticipants(const uuid_vec_t& uuids)  	}  	else  	{ -		// remember whom we have invited, to notify others later, when the invited ones actually join -		mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); +		if(findInstance(mSessionID)) +		{ +			// remember whom we have invited, to notify others later, when the invited ones actually join +			mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); +		}  		inviteToSession(uuids);  	} @@ -469,13 +472,18 @@ void LLFloaterIMSession::addP2PSessionParticipants(const LLSD& notification, con  	temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end());  	// then we can close the current session -	onClose(false); +	if(findInstance(mSessionID)) +	{ +		onClose(false); + +		// remember whom we have invited, to notify others later, when the invited ones actually join +		mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); +	}  	// we start a new session so reset the initialization flag  	mSessionInitialized = false; -	// remember whom we have invited, to notify others later, when the invited ones actually join -	mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); +  	// Start a new ad hoc voice call if we invite new participants to a P2P call,  	// or start a text chat otherwise. diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index ce6e639305..cc2859c099 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -212,7 +212,7 @@ void LLFloaterIMSessionTab::assignResizeLimits()  	mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed);      S32 participants_pane_target_width = is_participants_pane_collapsed? -    		0 : (mParticipantListPanel->getRect().getWidth() + LLPANEL_BORDER_WIDTH); +    		0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing());      S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth; @@ -241,7 +241,10 @@ BOOL LLFloaterIMSessionTab::postBuild()  	mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));  	mGearBtn = getChild<LLButton>("gear_btn"); - +    mAddBtn = getChild<LLButton>("add_btn"); +	mVoiceButton = getChild<LLButton>("voice_call_btn"); +    mTranslationCheckBox = getChild<LLUICtrl>("translate_chat_checkbox_lp"); +      	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");  	mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder"); @@ -372,7 +375,7 @@ void LLFloaterIMSessionTab::draw()  void LLFloaterIMSessionTab::enableDisableCallBtn()  { -    getChildView("voice_call_btn")->setEnabled( +    mVoiceButton->setEnabled(      		mSessionID.notNull()      		&& mSession      		&& mSession->mSessionInitialized @@ -758,7 +761,7 @@ void LLFloaterIMSessionTab::reshapeChatLayoutPanel()  void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show)  { -	getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE); +	mTranslationCheckBox->setVisible(mIsNearbyChat && show);  }  // static @@ -805,15 +808,10 @@ void LLFloaterIMSessionTab::reloadEmptyFloaters()  void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive)  { -	LLButton* voiceButton = getChild<LLButton>("voice_call_btn"); -	voiceButton->setImageOverlay( -			callIsActive? getString("call_btn_stop") : getString("call_btn_start")); - -	voiceButton->setToolTip( -			callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip")); +	mVoiceButton->setImageOverlay(callIsActive? getString("call_btn_stop") : getString("call_btn_start")); +	mVoiceButton->setToolTip(callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip"));  	enableDisableCallBtn(); -  }  void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self) @@ -898,6 +896,7 @@ void LLFloaterIMSessionTab::restoreFloater()  		mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));  		setMessagePaneExpanded(true);  		saveCollapsedState(); +		mInputEditor->enableSingleLineMode(false);  		enableResizeCtrls(true, true, true);  	}  } @@ -953,8 +952,8 @@ void LLFloaterIMSessionTab::updateGearBtn()  	if(prevVisibility != mGearBtn->getVisible())  	{  		LLRect gear_btn_rect =  mGearBtn->getRect(); -		LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect(); -		LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect(); +		LLRect add_btn_rect = mAddBtn->getRect(); +		LLRect call_btn_rect = mVoiceButton->getRect();  		S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;  		S32 right_shift = gear_btn_rect.getWidth() + gap_width;  		if(mGearBtn->getVisible()) @@ -968,24 +967,24 @@ void LLFloaterIMSessionTab::updateGearBtn()  			add_btn_rect.translate(-right_shift,0);  			call_btn_rect.translate(-right_shift,0);  		} -		getChild<LLButton>("add_btn")->setRect(add_btn_rect); -		getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect); +		mAddBtn->setRect(add_btn_rect); +		mVoiceButton->setRect(call_btn_rect);  	}  }  void LLFloaterIMSessionTab::initBtns()  {  	LLRect gear_btn_rect =  mGearBtn->getRect(); -	LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect(); -	LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect(); +	LLRect add_btn_rect = mAddBtn->getRect(); +	LLRect call_btn_rect = mVoiceButton->getRect();  	S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;  	S32 right_shift = gear_btn_rect.getWidth() + gap_width;  	add_btn_rect.translate(-right_shift,0);  	call_btn_rect.translate(-right_shift,0); -	getChild<LLButton>("add_btn")->setRect(add_btn_rect); -	getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect); +	mAddBtn->setRect(add_btn_rect); +	mVoiceButton->setRect(call_btn_rect);  }  // static @@ -1083,21 +1082,26 @@ void LLFloaterIMSessionTab::saveCollapsedState()  }  BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )  { +	BOOL handled = FALSE; +  	if(mask == MASK_ALT)  	{  		LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();  		if (KEY_RETURN == key && !isTornOff())  		{  			floater_container->expandConversation(); +			handled = TRUE;  		}  		if ((KEY_UP == key) || (KEY_LEFT == key))  		{  			floater_container->selectNextorPreviousConversation(false); +			handled = TRUE;  		}  		if ((KEY_DOWN == key ) || (KEY_RIGHT == key))  		{  			floater_container->selectNextorPreviousConversation(true); +			handled = TRUE;  		}  	} -	return TRUE; +	return handled;  } diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 302d5a8066..ba80d2369a 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -182,6 +182,9 @@ protected:  	LLButton* mTearOffBtn;  	LLButton* mCloseBtn;  	LLButton* mGearBtn; +	LLButton* mAddBtn; +    LLButton* mVoiceButton; +    LLUICtrl* mTranslationCheckBox;  private:  	// Handling selection and contextual menu diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 586965e5a0..c28657dbcd 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -74,6 +74,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )  		it != end_it;  		++it)  	{ +        // Recursive call to sort() on child (CHUI-849)  		LLFolderViewFolder* child_folderp = *it;  		sort(child_folderp); @@ -129,12 +130,12 @@ void LLFolderViewModelItemInventory::requestSort()  void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size)  {  	LLFolderViewModelItemCommon::setPassedFilter(passed, filter_generation, string_offset, string_size); - -	bool passed_filter_before = mPrevPassedAllFilters; +	bool before = mPrevPassedAllFilters;  	mPrevPassedAllFilters = passedFilter(filter_generation); -	if (passed_filter_before != mPrevPassedAllFilters) +    if (before != mPrevPassedAllFilters)  	{ +        // Need to rearrange the folder if the filtered state of the item changed  		LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder();  		if (parent_folder)  		{ @@ -150,11 +151,11 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite  	bool continue_filtering = true;  	if (item->getLastFilterGeneration() < filter_generation)  	{ -		// recursive application of the filter for child items +		// Recursive application of the filter for child items (CHUI-849)  		continue_filtering = item->filter( filter );  	} -	// track latest generation to pass any child items, for each folder up to root +	// Update latest generation to pass filter in parent and propagate up to root  	if (item->passedFilter())  	{  		LLFolderViewModelItemInventory* view_model = this; @@ -174,53 +175,61 @@ bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter)  	const S32 filter_generation = filter.getCurrentGeneration();  	const S32 must_pass_generation = filter.getFirstRequiredGeneration(); -	if (getLastFilterGeneration() >= must_pass_generation  +    if (getLastFilterGeneration() >= must_pass_generation  		&& getLastFolderFilterGeneration() >= must_pass_generation  		&& !passedFilter(must_pass_generation))  	{  		// failed to pass an earlier filter that was a subset of the current one -		// go ahead and flag this item as done +		// go ahead and flag this item as not pass  		setPassedFilter(false, filter_generation);  		setPassedFolderFilter(false, filter_generation);  		return true;  	} -	const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY)  -		? filter.checkFolder(this) -		: true; +    // *TODO : Revise the logic for fast pass on less restrictive filter case +    /* +     const S32 sufficient_pass_generation = filter.getFirstSuccessGeneration(); +    if (getLastFilterGeneration() >= sufficient_pass_generation +		&& getLastFolderFilterGeneration() >= sufficient_pass_generation +		&& passedFilter(sufficient_pass_generation)) +	{ +		// passed an earlier filter that was a superset of the current one +		// go ahead and flag this item as pass +		setPassedFilter(true, filter_generation); +		setPassedFolderFilter(true, filter_generation); +		return true; +	} +     */ +     +	const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) ? filter.checkFolder(this) : true;  	setPassedFolderFilter(passed_filter_folder, filter_generation); -	if(!mChildren.empty() +	bool continue_filtering = true; + +	if (!mChildren.empty()  		&& (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass -			|| descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement +            || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement  	{  		// now query children -		for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); -			iter != end_iter && filter.getFilterCount() > 0; -			++iter) +		for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); iter != end_iter; ++iter)  		{ -			if (!filterChildItem((*iter), filter)) +			continue_filtering = filterChildItem((*iter), filter); +            if (!continue_filtering)  			{  				break;  			}  		}  	} -	// if we didn't use all filter iterations -	// that means we filtered all of our descendants -	// so filter ourselves now -	if (filter.getFilterCount() > 0) +	// If we didn't use all the filter time that means we filtered all of our descendants so we can filter ourselves now +    if (continue_filtering)  	{ -		filter.decrementFilterCount(); - +        // This is where filter check on the item done (CHUI-849)  		const bool passed_filter = filter.check(this);  		setPassedFilter(passed_filter, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize()); -		return true; -	} -	else -	{ -		return false; +        continue_filtering = !filter.isTimedOut();  	} +    return continue_filtering;  }  LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() @@ -307,8 +316,8 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a,  	}  } -LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model )  -	:	LLFolderViewModelItemCommon(root_view_model), -	mPrevPassedAllFilters(false) +LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model ) : +    LLFolderViewModelItemCommon(root_view_model), +    mPrevPassedAllFilters(false)  {  } diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index 890d03d1c9..9dcfdfa185 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -59,9 +59,8 @@ public:  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0;  	virtual LLToolDragAndDrop::ESource getDragSource() const = 0; -  protected: -	bool								mPrevPassedAllFilters; +    bool mPrevPassedAllFilters;  };  class LLInventorySort diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index a0f2918bd7..302d21c2e4 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -116,6 +116,80 @@ public:  };  LLGroupHandler gGroupHandler; +// This object represents a pending request for specified group member information +// which is needed to check whether avatar can leave group +class LLFetchGroupMemberData : public LLGroupMgrObserver +{ +public: +	LLFetchGroupMemberData(const LLUUID& group_id) :  +		mGroupId(group_id), +		mRequestProcessed(false), +		LLGroupMgrObserver(group_id)  +	{ +		llinfos << "Sending new group member request for group_id: "<< group_id << llendl; +		LLGroupMgr* mgr = LLGroupMgr::getInstance(); +		// register ourselves as an observer +		mgr->addObserver(this); +		// send a request +		mgr->sendGroupPropertiesRequest(group_id); +		mgr->sendCapGroupMembersRequest(group_id); +	} + +	~LLFetchGroupMemberData() +	{ +		if (!mRequestProcessed) +		{ +			// Request is pending +			llwarns << "Destroying pending group member request for group_id: " +				<< mGroupId << llendl; +		} +		// Remove ourselves as an observer +		LLGroupMgr::getInstance()->removeObserver(this); +	} + +	void changed(LLGroupChange gc) +	{ +		if (gc == GC_MEMBER_DATA && !mRequestProcessed) +		{ +			LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId); +			if (!gdatap) +			{ +				llwarns << "LLGroupMgr::getInstance()->getGroupData() was NULL" << llendl; +			}  +			else if (!gdatap->isMemberDataComplete()) +			{ +				llwarns << "LLGroupMgr::getInstance()->getGroupData()->isMemberDataComplete() was FALSE" << llendl; +			} +			else +			{ +				processGroupData(); +				mRequestProcessed = true; +			} +		} +	} + +	LLUUID getGroupId() { return mGroupId; } +	virtual void processGroupData() = 0; +protected: +	LLUUID mGroupId; +private: +	bool mRequestProcessed; +}; + +class LLFetchLeaveGroupData: public LLFetchGroupMemberData +{ +public: +	 LLFetchLeaveGroupData(const LLUUID& group_id) +		 : LLFetchGroupMemberData(group_id) +	 {} +	 void processGroupData() +	 { +		 LLGroupActions::processLeaveGroupDataResponse(mGroupId); +	 } +}; + +LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL; +  // static  void LLGroupActions::search()  { @@ -208,23 +282,52 @@ bool LLGroupActions::onJoinGroup(const LLSD& notification, const LLSD& response)  void LLGroupActions::leave(const LLUUID& group_id)  {  	if (group_id.isNull()) +	{  		return; +	} -	S32 count = gAgent.mGroups.count(); -	S32 i; -	for (i = 0; i < count; ++i) +	LLGroupData group_data; +	if (gAgent.getGroupData(group_id, group_data))  	{ -		if(gAgent.mGroups.get(i).mID == group_id) -			break; +		LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); +		if (!gdatap || !gdatap->isMemberDataComplete()) +		{ +			if (gFetchLeaveGroupData != NULL) +			{ +				delete gFetchLeaveGroupData; +				gFetchLeaveGroupData = NULL; +			} +			gFetchLeaveGroupData = new LLFetchLeaveGroupData(group_id); +		} +		else +		{ +			processLeaveGroupDataResponse(group_id); +		}  	} -	if (i < count) +} + +//static +void LLGroupActions::processLeaveGroupDataResponse(const LLUUID group_id) +{ +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); +	LLUUID agent_id = gAgent.getID(); +	LLGroupMgrGroupData::member_list_t::iterator mit = gdatap->mMembers.find(agent_id); +	//get the member data for the group +	if ( mit != gdatap->mMembers.end() )  	{ -		LLSD args; -		args["GROUP"] = gAgent.mGroups.get(i).mName; -		LLSD payload; -		payload["group_id"] = group_id; -		LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup); +		LLGroupMemberData* member_data = (*mit).second; + +		if ( member_data && member_data->isOwner() && gdatap->mMemberCount == 1) +		{ +			LLNotificationsUtil::add("OwnerCannotLeaveGroup"); +			return; +		}  	} +	LLSD args; +	args["GROUP"] = gdatap->mName; +	LLSD payload; +	payload["group_id"] = group_id; +	LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);  }  // static diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h index 3f9852f194..afc4686dd7 100644 --- a/indra/newview/llgroupactions.h +++ b/indra/newview/llgroupactions.h @@ -114,6 +114,14 @@ public:  private:  	static bool onJoinGroup(const LLSD& notification, const LLSD& response);  	static bool onLeaveGroup(const LLSD& notification, const LLSD& response); +	 +	/** +	 * This function is called by LLFetchLeaveGroupData upon receiving a response to a group  +	 * members data request. +	 */ +	static void processLeaveGroupDataResponse(const LLUUID group_id); + +	friend class LLFetchLeaveGroupData;  };  #endif // LL_LLGROUPACTIONS_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 2c20409381..214b177a1b 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -103,6 +103,7 @@ BOOL LLSessionTimeoutTimer::tick()  } +void notify_of_message(const LLSD& msg, bool is_dnd_msg);  void process_dnd_im(const LLSD& notification)  { @@ -129,15 +130,9 @@ void process_dnd_im(const LLSD& notification)              fromID,               false,               false); //will need slight refactor to retrieve whether offline message or not (assume online for now) +	} -		LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); -		 -		if (im_box) -		{ -			im_box->flashConversationItemWidget(sessionID, true); -		} - -    } +	notify_of_message(data, true);  } @@ -158,88 +153,89 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,  	LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));  } -void on_new_message(const LLSD& msg) +void notify_of_message(const LLSD& msg, bool is_dnd_msg)  { -    std::string user_preferences; -    LLUUID participant_id = msg["from_id"].asUUID(); -    LLUUID session_id = msg["session_id"].asUUID(); -    LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); +	std::string user_preferences; +	LLUUID participant_id = msg[is_dnd_msg ? "FROM_ID" : "from_id"].asUUID(); +	LLUUID session_id = msg[is_dnd_msg ? "SESSION_ID" : "session_id"].asUUID(); +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); -    // do not show notification which goes from agent -    if (gAgent.getID() == participant_id) -    { -        return; -    } - -    // determine state of conversations floater -    enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status; +	// do not show notification which goes from agent +	if (gAgent.getID() == participant_id) +	{ +		return; +	} +	// determine state of conversations floater +	enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status; -    LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); +	LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");  	LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); +	bool store_dnd_message = false; // flag storage of a dnd message  	if (!LLFloater::isVisible(im_box) || im_box->isMinimized())  	{  		conversations_floater_status = CLOSED;  	}  	else if (!im_box->hasFocus() && -			    !(session_floater && LLFloater::isVisible(session_floater) -	            && !session_floater->isMinimized() && session_floater->hasFocus())) +		!(session_floater && LLFloater::isVisible(session_floater) +		&& !session_floater->isMinimized() && session_floater->hasFocus()))  	{  		conversations_floater_status = NOT_ON_TOP;  	}  	else if (im_box->getSelectedSession() != session_id)  	{  		conversations_floater_status = ON_TOP; -    } +	}  	else  	{  		conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED;  	} -    //  determine user prefs for this session -    if (session_id.isNull()) -    { -    	user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions"); -    } -    else if(session->isP2PSessionType()) -    { -        if (LLAvatarTracker::instance().isBuddy(participant_id)) -        { -        	user_preferences = gSavedSettings.getString("NotificationFriendIMOptions"); -        } -        else -        { -        	user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions"); -        } -    } -    else if(session->isAdHocSessionType()) -    { -    	user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions"); -    } -    else if(session->isGroupSessionType()) -    { -    	user_preferences = gSavedSettings.getString("NotificationGroupChatOptions"); -    } - -    // actions: +	//  determine user prefs for this session +	if (session_id.isNull()) +	{ +		user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions"); +	} +	else if(session->isP2PSessionType()) +	{ +		if (LLAvatarTracker::instance().isBuddy(participant_id)) +		{ +			user_preferences = gSavedSettings.getString("NotificationFriendIMOptions"); +		} +		else +		{ +			user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions"); +		} +	} +	else if(session->isAdHocSessionType()) +	{ +		user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions"); +	} +	else if(session->isGroupSessionType()) +	{ +		user_preferences = gSavedSettings.getString("NotificationGroupChatOptions"); +	} -    // 0. nothing - exit -    if (("none" == user_preferences || -    		ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status) -    	    && session_floater->isMessagePaneExpanded()) -    { -    	return; -    } +	// actions: -    // 1. open floater and [optional] surface it -    if ("openconversations" == user_preferences && -    		(CLOSED == conversations_floater_status -    				|| NOT_ON_TOP == conversations_floater_status)) -    { -    	if(!gAgent.isDoNotDisturb()) -        { +	// 0. nothing - exit +	if (("none" == user_preferences || +		ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status) +		&& session_floater->isMessagePaneExpanded()) +	{ +		return; +	} +	 +	// 1. open floater and [optional] surface it +	if (("openconversations" == user_preferences && +		(CLOSED == conversations_floater_status +		|| NOT_ON_TOP == conversations_floater_status)) +		|| is_dnd_msg ) +	{ +		if(!gAgent.isDoNotDisturb()) +		{  			// Open conversations floater  			LLFloaterReg::showInstance("im_container");  			im_box->collapseMessagesPane(false); @@ -261,57 +257,100 @@ void on_new_message(const LLSD& msg)  				}  			}  		} -        else -        { -            //If in DND mode, allow notification to be stored so upon DND exit -            //useMostItrusiveIMNotification will be called to notify user a message exists -            if(session_id.notNull() -               && participant_id.notNull() -		       && !session_floater->isShown()) -            { -                LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); -	        } -        } -    } +		else +		{ +			store_dnd_message = true; +		} -    // 2. Flash line item -    if ("openconversations" == user_preferences -    		|| ON_TOP == conversations_floater_status -    		|| ("toast" == user_preferences && ON_TOP != conversations_floater_status) -    		|| ("flash" == user_preferences && CLOSED == conversations_floater_status)) -    { -    	if(!LLMuteList::getInstance()->isMuted(participant_id)) -    	{ -    		im_box->flashConversationItemWidget(session_id, true); -    	} -    } +	} -    // 3. Flash FUI button -    if (("toast" == user_preferences || "flash" == user_preferences) && -    		(CLOSED == conversations_floater_status -    		    || NOT_ON_TOP == conversations_floater_status)) -    { -    	if(!LLMuteList::getInstance()->isMuted(participant_id) -            && !gAgent.isDoNotDisturb()) -    	{ -    		gToolBarView->flashCommand(LLCommandId("chat"), true); -    	} -    } +	// 2. Flash line item +	if ("openconversations" == user_preferences +		|| ON_TOP == conversations_floater_status +		|| ("toast" == user_preferences && ON_TOP != conversations_floater_status) +		|| ("flash" == user_preferences && CLOSED == conversations_floater_status) +		|| is_dnd_msg) +	{ +		if(!LLMuteList::getInstance()->isMuted(participant_id)) +		{ +			if(gAgent.isDoNotDisturb()) +			{ +				store_dnd_message = true; +			} +			else +			{ +				if (is_dnd_msg && (ON_TOP == conversations_floater_status ||  +									NOT_ON_TOP == conversations_floater_status ||  +									CLOSED == conversations_floater_status)) +				{ +					im_box->highlightConversationItemWidget(session_id, true); +				} +				else +				{ +					im_box->flashConversationItemWidget(session_id, true); +				} +			} +		} +	} -    // 4. Toast -    if ((("toast" == user_preferences) && -    		(CLOSED == conversations_floater_status -    		    || NOT_ON_TOP == conversations_floater_status)) -    		    || !session_floater->isMessagePaneExpanded()) +	// 3. Flash FUI button +	if (("toast" == user_preferences || "flash" == user_preferences) && +		(CLOSED == conversations_floater_status +		|| NOT_ON_TOP == conversations_floater_status) +		&& !is_dnd_msg) //prevent flashing FUI button because the conversation floater will have already opened +	{ +		if(!LLMuteList::getInstance()->isMuted(participant_id)) +		{ +			if(!gAgent.isDoNotDisturb()) +			{ +				gToolBarView->flashCommand(LLCommandId("chat"), true); +			} +			else +			{ +				store_dnd_message = true; +			} +		} +	} -    { -        //Show IM toasts (upper right toasts) -        // Skip toasting for system messages and for nearby chat -        if(session_id.notNull() && participant_id.notNull()) -        { -            LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); -        } -    } +	// 4. Toast +	if ((("toast" == user_preferences) && +		(ON_TOP_AND_ITEM_IS_SELECTED != conversations_floater_status)) +		|| !session_floater->isMessagePaneExpanded()) + +	{ +		//Show IM toasts (upper right toasts) +		// Skip toasting for system messages and for nearby chat +		if(session_id.notNull() && participant_id.notNull()) +		{ +			if(!is_dnd_msg) +			{ +				if(gAgent.isDoNotDisturb()) +				{ +					store_dnd_message = true; +				} +				else +				{ +					LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); +				} +			} +		} +	} +	if (store_dnd_message) +	{ +		// If in DND mode, allow notification to be stored so upon DND exit  +		// the user will be notified with some limitations (see 'is_dnd_msg' flag checks) +		if(session_id.notNull() +			&& participant_id.notNull() +			&& !session_floater->isShown()) +		{ +			LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); +		} +	} +} + +void on_new_message(const LLSD& msg) +{ +	notify_of_message(msg, false);  }  LLIMModel::LLIMModel()  diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 92f2d33073..3c6974cf6d 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -70,11 +70,8 @@ LLInventoryFilter::LLInventoryFilter(const Params& p)  	mFilterSubString(p.substring),  	mCurrentGeneration(0),  	mFirstRequiredGeneration(0), -	mFirstSuccessGeneration(0), -	mFilterCount(0) +	mFirstSuccessGeneration(0)  { -	mNextFilterGeneration = mCurrentGeneration + 1; -  	// copy mFilterOps into mDefaultFilterOps  	markDefault();  } @@ -92,9 +89,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)  		return passed_clipboard;  	} -	std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; - -	BOOL passed = (mFilterSubString.size() == 0 || string_offset != std::string::npos); +	bool passed = (mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) != std::string::npos : true);  	passed = passed && checkAgainstFilterType(listener);  	passed = passed && checkAgainstPermissions(listener);  	passed = passed && checkAgainstFilterLinks(listener); @@ -105,17 +100,12 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)  bool LLInventoryFilter::check(const LLInventoryItem* item)  { -	std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; - +	const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true);  	const bool passed_filtertype = checkAgainstFilterType(item);  	const bool passed_permissions = checkAgainstPermissions(item); -	const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID()); -	const bool passed = (passed_filtertype  -		&& passed_permissions -		&& passed_clipboard  -		&&	(mFilterSubString.size() == 0 || string_offset != std::string::npos)); +	const bool passed_clipboard = checkAgainstClipboard(item->getUUID()); -	return passed; +	return passed_filtertype && passed_permissions && passed_clipboard && passed_string;  }  bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const @@ -439,7 +429,7 @@ void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)  		current_types = types;  		if (more_bits_set && fewer_bits_set)  		{ -			// neither less or more restrive, both simultaneously +			// neither less or more restrictive, both simultaneously  			// so we need to filter from scratch  			setModified(FILTER_RESTART);  		} @@ -714,7 +704,7 @@ void LLInventoryFilter::resetDefault()  void LLInventoryFilter::setModified(EFilterModified behavior)  {  	mFilterText.clear(); -	mCurrentGeneration = mNextFilterGeneration++; +	mCurrentGeneration++;  	if (mFilterModified == FILTER_NONE)  	{ @@ -1021,21 +1011,19 @@ LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const  	return mFilterOps.mShowFolderState;   } -void LLInventoryFilter::setFilterCount(S32 count)  -{  -	mFilterCount = count;  -} -S32 LLInventoryFilter::getFilterCount() const +bool LLInventoryFilter::isTimedOut()  { -	return mFilterCount; +	return mFilterTime.hasExpired();  } -void LLInventoryFilter::decrementFilterCount()  -{  -	mFilterCount--;  +void LLInventoryFilter::resetTime(S32 timeout) +{ +	mFilterTime.reset(); +    F32 time_in_sec = (F32)(timeout)/1000.0; +	mFilterTime.setTimerExpirySec(time_in_sec);  } -S32 LLInventoryFilter::getCurrentGeneration() const  +S32 LLInventoryFilter::getCurrentGeneration() const  {   	return mCurrentGeneration;  } diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 4912b5ca91..ce516af0b9 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -215,12 +215,11 @@ public:  	void 				setModified(EFilterModified behavior = FILTER_RESTART);  	// +-------------------------------------------------------------------+ -	// + Count +	// + Time  	// +-------------------------------------------------------------------+ -	void 				setFilterCount(S32 count); -	S32 				getFilterCount() const; -	void 				decrementFilterCount(); - +	void 				resetTime(S32 timeout); +    bool                isTimedOut(); +      	// +-------------------------------------------------------------------+  	// + Default  	// +-------------------------------------------------------------------+ @@ -262,13 +261,15 @@ private:  	const std::string		mName;  	S32						mCurrentGeneration; +    // The following makes checking for pass/no pass possible even if the item is not checked against the current generation +    // Any item that *did not pass* the "required generation" will *not pass* the current one +    // Any item that *passes* the "success generation" will *pass* the current one  	S32						mFirstRequiredGeneration;  	S32						mFirstSuccessGeneration; -	S32						mNextFilterGeneration; -	S32						mFilterCount;  	EFilterModified 		mFilterModified; - +	LLTimer                 mFilterTime; +      	std::string 			mFilterText;  	std::string 			mEmptyLookupMessage;  }; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index cf1fd4c0d0..e5b9e11d48 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -192,7 +192,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )      p.show_item_link_overlays = mShowItemLinkOverlays;      p.root = NULL;      p.options_menu = "menu_inventory.xml"; -	 +      return LLUICtrlFactory::create<LLFolderView>(p);  } @@ -396,6 +396,7 @@ LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()  	return getFilter().getShowFolderState();  } +// Called when something changed in the global model (new item, item coming through the wire, rename, move, etc...) (CHUI-849)  void LLInventoryPanel::modelChanged(U32 mask)  {  	static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 2d7454b636..379bbc5f8d 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -631,7 +631,7 @@ void LLLogChat::deleteTranscripts()  }  // static -bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id) +bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id, bool is_group)  {  	std::vector<std::string> list_of_transcriptions;  	LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); @@ -641,20 +641,53 @@ bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id)  		LLAvatarName avatar_name;  		LLAvatarNameCache::get(avatar_id, &avatar_name);  		std::string avatar_user_name = avatar_name.getAccountName(); -		std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_'); - -		BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) +		if(!is_group)  		{ -			if (std::string::npos != transcript_file_name.find(avatar_user_name)) +			std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_'); +			BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)  			{ -				return true; +				if (std::string::npos != transcript_file_name.find(avatar_user_name)) +				{ +					return true; +				}  			}  		} +		else +		{ +			std::string file_name; +			gCacheName->getGroupName(avatar_id, file_name); +			file_name = makeLogFileName(file_name); +			BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) +			{ +				if (transcript_file_name == file_name) +				{ +					return true; +				} +			} +		} +  	}  	return false;  } +bool LLLogChat::isNearbyTranscriptExist() +{ +	std::vector<std::string> list_of_transcriptions; +	LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); + +	std::string file_name; +	file_name = makeLogFileName("chat"); +	BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) +	{ +	   	if (transcript_file_name == file_name) +	   	{ +			return true; +		 } +	} +	return false; +} +  //*TODO mark object's names in a special way so that they will be distinguishable form avatar name   //which are more strict by its nature (only firstname and secondname)  //Example, an object's name can be written like "Object <actual_object's_name>" diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index e819f00dd9..bd70dbaac9 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -67,7 +67,8 @@ public:  		std::vector<std::string>& listOfFilesToMove);  	static void deleteTranscripts(); -	static bool isTranscriptExist(const LLUUID& avatar_id); +	static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false); +	static bool isNearbyTranscriptExist();  private:  	static std::string cleanFileName(std::string filename); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index d6535c88e9..53deded2f2 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -130,6 +130,8 @@ BOOL LLPanelMainInventory::postBuild()  	mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");  	mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this)); +    mCounterCtrl = getChild<LLUICtrl>("ItemcountText"); +      	//panel->getFilter().markDefault();  	// Set up the default inv. panel/filter settings. @@ -566,7 +568,7 @@ void LLPanelMainInventory::draw()  void LLPanelMainInventory::updateItemcountText()  {  	// *TODO: Calling setlocale() on each frame may be inefficient. -	LLLocale locale(LLStringUtil::getLocale()); +	//LLLocale locale(LLStringUtil::getLocale());  	std::string item_count_string;  	LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount()); @@ -589,8 +591,7 @@ void LLPanelMainInventory::updateItemcountText()  		text = getString("ItemcountUnknown");  	} -	// *TODO: Cache the LLUICtrl* for the ItemcountText control -	getChild<LLUICtrl>("ItemcountText")->setValue(text); +    mCounterCtrl->setValue(text);  }  void LLPanelMainInventory::onFocusReceived() diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 899931aa89..394b004e20 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -121,6 +121,7 @@ private:  	LLFilterEditor*				mFilterEditor;  	LLTabContainer*				mFilterTabs; +    LLUICtrl*                   mCounterCtrl;  	LLHandle<LLFloater>			mFinderHandle;  	LLInventoryPanel*			mActivePanel;  	bool						mResortActivePanel; diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index 75e6e3d13a..025ef3945d 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -28,6 +28,7 @@  #include "lltoastimpanel.h"  #include "llagent.h" +#include "llavatarnamecache.h"  #include "llfloaterreg.h"  #include "llgroupactions.h"  #include "llgroupiconctrl.h" @@ -61,6 +62,15 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  	style_params.font.name(font_name);  	style_params.font.size(font_size); +	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(p.session_id); +	mIsGroupMsg = (im_session->mSessionType == LLIMModel::LLIMSession::GROUP_SESSION); +	if(mIsGroupMsg) +	{ +		mAvatarName->setValue(im_session->mName); +		LLAvatarName avatar_name; +		LLAvatarNameCache::get(p.avatar_id, &avatar_name); +		p.message = "[From " + avatar_name.getDisplayName() + "]\n" + p.message; +	}  	//Handle IRC styled /me messages.  	std::string prefix = p.message.substr(0, 4); @@ -81,12 +91,17 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  		mMessage->setText(p.message, style_params);  	} -	mAvatarName->setValue(p.from); +	if(!mIsGroupMsg) +	{ +		mAvatarName->setValue(p.from); +	}  	mTime->setValue(p.time);  	mSessionID = p.session_id;  	mAvatarID = p.avatar_id;  	mNotification = p.notification; + +  	initIcon();  	S32 maxLinesCount; @@ -147,7 +162,14 @@ void LLToastIMPanel::spawnNameToolTip()  	LLToolTip::Params params;  	params.background_visible(false); -	params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE)); +	if(!mIsGroupMsg) +	{ +		params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE)); +	} +	else +	{ +		params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_group", LLSD().with("group_id", mSessionID), FALSE)); +	}  	params.delay_time(0.0f);		// spawn instantly on hover  	params.image(LLUI::getUIImage("Info_Small"));  	params.message(""); diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index 3eb11fb3bc..767617dabc 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -73,6 +73,8 @@ private:  	LLTextBox*			mAvatarName;  	LLTextBox*			mTime;  	LLTextBox*			mMessage; + +	bool                mIsGroupMsg;  };  #endif // LLTOASTIMPANEL_H_ diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 3c0d6189ac..3a57e2a3c9 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2641,7 +2641,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			{  				send_do_not_disturb_message(msg, from_id);  			} -			else +			 +			if (!is_muted)  			{  				LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL;  				// Read the binary bucket for more information. diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 0910b7536d..a427770403 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1810,7 +1810,6 @@ void LLViewerWindow::initBase()  	gFloaterView = main_view->getChild<LLFloaterView>("Floater View");  	gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());  	gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View"); -	  	// Console  	llassert( !gConsole ); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 0de217fc0d..ac1289c4b8 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -864,4 +864,19 @@    <color      name="blue"      value="0 0 1 1"/> + +  <!--Resize bar colors --> + +  <color +    name="ResizebarBorderLight" +    value="0.231 0.231 0.231 1"/> + +  <color +    name="ResizebarBorderDark" +    value="0.133 0.133 0.133 1"/> + +  <color +    name="ResizebarBody" +    value="0.208 0.208 0.208 1"/> +      </colors> diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index fcab966dee..5b17ef94db 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -773,4 +773,7 @@ with the same filename but different name    <texture name="Popup_Caution" file_name="icons/pop_up_caution.png"/>    <texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>    <texture name="NavBar Separator" file_name="navbar/separator.png"/> + +  <texture name="Horizontal Drag Handle" file_name="widgets/horizontal_drag_handle.png"/> +  <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png"/>  </textures> diff --git a/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.pngBinary files differ new file mode 100644 index 0000000000..642eac4065 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png diff --git a/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.pngBinary files differ new file mode 100644 index 0000000000..b06b70cf36 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 65f623a47e..da016462db 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -24,24 +24,28 @@       value="Conv_toolbar_expand"/>      <layout_stack       animate="true"  -     bottom="-1" +     bottom="-5" +     drag_handle_gap="6" +     drag_handle_first_indent="27" +     drag_handle_second_indent="10"       follows="all"       layout="topleft"       left="0"       name="conversations_stack"       orientation="horizontal"       right="-1" +     show_drag_handle="true"       top="0">          <layout_panel           auto_resize="false"           user_resize="true"                   name="conversations_layout_panel"           min_dim="38" -         expanded_min_dim="156"> +         expanded_min_dim="136">              <layout_stack               animate="false"                follows="left|top|right" -             height="35" +             height="27"               layout="topleft"               left="0"               name="conversations_pane_buttons_stack" @@ -50,7 +54,6 @@               top="0">                  <layout_panel                   auto_resize="true" -                 height="35"                   name="conversations_pane_buttons_expanded">                      <menu_button                       follows="top|left" @@ -64,7 +67,7 @@                       left="5"                       name="sort_btn"                       tool_tip="View/sort options" -                     top="5" +                     top="1"                       width="31" />                      <button                       follows="top|left" @@ -74,7 +77,7 @@                       image_selected="Toolbar_Middle_Selected"                       image_unselected="Toolbar_Middle_Off"                       layout="topleft" -                     top="5" +                     top="1"                       left_pad="2"                       name="add_btn"                       tool_tip="Start a new conversation" @@ -87,7 +90,7 @@                       image_selected="Toolbar_Middle_Selected"                       image_unselected="Toolbar_Middle_Off"                       layout="topleft" -                     top="5" +                     top="1"                       left_pad="2"                       name="speak_btn"                       tool_tip="Speak with people using your microphone" @@ -95,9 +98,8 @@                  </layout_panel>                  <layout_panel                   auto_resize="false" -                 height="35"                   name="conversations_pane_buttons_collapsed" -                 width="41"> +                 width="31">                      <button                       follows="right|top"                       height="25" @@ -106,8 +108,8 @@                       image_selected="Toolbar_Middle_Selected"                       image_unselected="Toolbar_Middle_Off"                       layout="topleft" -                     top="5" -                     left="1" +                     top="1" +                     left="0"                       name="expand_collapse_btn"                       tool_tip="Collapse/Expand this list"                       width="31" /> @@ -119,7 +121,7 @@               layout="topleft"               name="conversations_list_panel"               opaque="true" -             top="35" +             top_pad="0"               left="5"               right="-1"/>          </layout_panel> @@ -127,7 +129,7 @@           auto_resize="true"           user_resize="true"           name="messages_layout_panel" -         expanded_min_dim="222"> +         expanded_min_dim="212">              <panel_container               bottom="-1"               follows="all" @@ -136,44 +138,44 @@               name="im_box_tab_container"               right="-1"               top="0"> -             <panel -               bottom="-1" -               follows="all" -               layout="topleft" -               name="stub_panel" -               opaque="true" -               top_pad="0" -               left="0" -               right="-1"> -                 <button -                 follows="right|top" -                 height="25" -                 image_hover_unselected="Toolbar_Middle_Over" -                 image_overlay="Conv_toolbar_collapse" -                 image_selected="Toolbar_Middle_Selected" -                 image_unselected="Toolbar_Middle_Off" +                <panel +                 bottom="-1" +                 follows="all"                   layout="topleft" -                 top="5" -                 right="-10" -                 name="stub_collapse_btn" -                 tool_tip="Collapse this pane" -                 width="31" /> -                 <text -                   type="string" -                   clip_partial="false" -                   follows="left|top|right" -                   layout="topleft" -                   left="15" -                   right="-15" -                   name="stub_textbox" -                   top="25" -                   height="40" -                   valign="center" -                   parse_urls="true" -                   wrap="true"> -                   This conversation is in a separate window.   [secondlife:/// Bring it back.] -                 </text> -             </panel> +                 name="stub_panel" +                 opaque="true" +                 top_pad="0" +                 left="0" +                 right="-1"> +                    <button +                     follows="right|top" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="Conv_toolbar_collapse" +                     image_selected="Toolbar_Middle_Selected" +                     image_unselected="Toolbar_Middle_Off" +                     layout="topleft" +                     top="1" +                     right="-10" +                     name="stub_collapse_btn" +                     tool_tip="Collapse this pane" +                     width="31" /> +                    <text +                     type="string" +                     clip_partial="false" +                     follows="left|top|right" +                     layout="topleft" +                     left="15" +                     right="-15" +                     name="stub_textbox" +                     top="25" +                     height="40" +                     valign="center" +                     parse_urls="true" +                     wrap="true"> +                         This conversation is in a separate window.   [secondlife:/// Bring it back.] +                    </text> +                </panel>              </panel_container>          </layout_panel>      </layout_stack> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 2152a9f6e9..8da4213c65 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -70,26 +70,23 @@       top="0"       left="0"       right="-1" -     bottom="-3"> +     bottom="-1">          <layout_stack           animate="false"  +         bottom="-1"           default_tab_group="2"           follows="all" -         right="-5" -         bottom="-1" -         top="0" -         left="5" -         border_size="0" +         left="3"           layout="topleft" -         orientation="vertical"           name="main_stack" -         tab_group="1"> +         right="-3" +         orientation="vertical" +         tab_group="1" +         top="0">              <layout_panel               auto_resize="false"               name="toolbar_panel" -             height="35" -             right="-1" -             left="1"> +             height="25">                  <menu_button                   menu_filename="menu_im_session_showmodes.xml"                   follows="top|left" @@ -102,7 +99,7 @@                   left="5"                   name="view_options_btn"                   tool_tip="View/sort options" -                 top="5" +                 top="1"                   width="31" />                  <menu_button                   menu_filename="menu_im_conversation.xml" @@ -113,7 +110,7 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" +                 top="1"                   left_pad="2"                   name="gear_btn"                   visible="false" @@ -128,7 +125,7 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" +                 top="1"                   left_pad="2"                   name="add_btn"                   tool_tip="Add someone to this conversation" @@ -141,7 +138,7 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" +                 top="1"                   left_pad="2"                   name="voice_call_btn"                   tool_tip="Open voice connection" @@ -166,8 +163,8 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" -                 right="-67" +                 top="1" +                 right="-70"                   name="close_btn"                   tool_tip="End this conversation"                   width="31" /> @@ -179,7 +176,7 @@                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 top="5" +                 top="1"                   left_pad="2"                   name="expand_collapse_btn"                   tool_tip="Collapse/Expand this pane" @@ -194,18 +191,21 @@                   layout="topleft"                   left_pad="2"                   name="tear_off_btn" -                 top="5" +                 top="1"                   width="31" />              </layout_panel>              <layout_panel               name="body_panel" -             top="1" -             bottom="-1"> +             height="235">                  <layout_stack                   default_tab_group="2" +                 drag_handle_gap="6" +                 drag_handle_first_indent="0" +                 drag_handle_second_indent="1"                   follows="all"                   orientation="horizontal"                   name="im_panels" +                 show_drag_handle="true"                   tab_group="1"                   top="0"                   right="-1" @@ -217,14 +217,12 @@                       min_dim="0"                       width="150"                        user_resize="true" -                     auto_resize="false"  -                     bottom="-1" /> +                     auto_resize="false" />                      <layout_panel                       default_tab_group="3"                       tab_group="2"                       name="right_part_holder" -                     min_width="221" -                     bottom="-1"> +                     min_width="172">                          <layout_stack                           animate="true"                            default_tab_group="2" @@ -233,7 +231,7 @@                           name="translate_and_chat_stack"                           tab_group="1"                           top="0" -                         left="0" +                         left="1"                           right="-1"                           bottom="-1">                              <layout_panel @@ -259,7 +257,7 @@                                   parse_highlights="true"                                   parse_urls="true"                                   right="-1" -                                 left="5" +                                 left="0"                                   top="0"                                   bottom="-1" />                              </layout_panel> @@ -268,10 +266,7 @@                  </layout_stack>              </layout_panel>              <layout_panel -             top_delta="0" -             top="0" -             height="26" -             bottom="-1" +             height="35"               auto_resize="false"               name="chat_layout_panel">                  <layout_stack @@ -281,15 +276,11 @@                   orientation="horizontal"                   name="input_panels"                   top="0" -                 bottom="-2" +                 bottom="-1"                   left="0"                   right="-1">                      <layout_panel -                     name="input_editor_layout_panel" -                     auto_resize="true" -                     user_resize="false" -                     top="0" -                     bottom="-1"> +                     name="input_editor_layout_panel">                          <chat_editor                           layout="topleft"                           expand_lines_count="5" @@ -302,32 +293,27 @@                           max_length="1023"                           spellcheck="true"                           tab_group="3" -                         top="1" -                         bottom="-2" -                         left="4" -                         right="-4" +                         bottom="-8" +                         left="5" +                         right="-5"                           wrap="true" />                      </layout_panel>                      <layout_panel                       auto_resize="false" -                     user_resize="false"                       name="input_button_layout_panel" -                     width="30" -                     top="0" -                     bottom="-1"> +                     width="32">                          <button -                         layout="topleft"                           left="1" -                         right="-1" -                         top="1" -                         height="22" +                         top="4" +                         height="25"                           follows="left|right|top"                           image_hover_unselected="Toolbar_Middle_Over"                           image_overlay="Conv_expand_one_line"                           image_selected="Toolbar_Middle_Selected"                           image_unselected="Toolbar_Middle_Off"                           name="minz_btn" -                         tool_tip="Shows/hides message panel" /> +                         tool_tip="Shows/hides message panel" +                         width="28" />                      </layout_panel>                  </layout_stack>              </layout_panel> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 105bef7321..bb3044a0d5 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3649,6 +3649,17 @@ Leave Group?    </notification>    <notification +   icon="alertmodal.tga" +   name="OwnerCannotLeaveGroup" +   type="alertmodal"> +    Unable to leave group. You cannot leave the group because you are the last owner of the group. Please assign another member to the owner role first. +    <tag>group</tag> +    <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification     icon="alert.tga"     name="ConfirmKick"     type="alert"> @@ -6513,7 +6524,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th     icon="notify.tga"     name="JoinGroup"     persist="true" -   type="notify"> +   type="offer">      <tag>group</tag>  [MESSAGE]      <form name="form"> | 
