diff options
198 files changed, 4669 insertions, 1475 deletions
| diff --git a/doc/contributions.txt b/doc/contributions.txt index 4b36c44a5f..cf10ecccfb 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -600,6 +600,7 @@ Tharax Ferraris  Thickbrick Sleaford  	VWR-7109  	VWR-9287 +	VWR-13483  	VWR-13947  Thraxis Epsilon  	SVC-371 diff --git a/indra/develop.py b/indra/develop.py index 05ad12f20e..eaecdd0ab6 100755 --- a/indra/develop.py +++ b/indra/develop.py @@ -573,7 +573,7 @@ class WindowsSetup(PlatformSetup):              if self.gens[self.generator]['ver'] in [ r'8.0', r'9.0' ]:                  config = '\"%s|Win32\"' % config -            return "buildconsole %s.sln /build %s" % (self.project_name, config) +            return "buildconsole %(prj)s.sln /build /cfg=%(cfg)s" % {'prj': self.project_name, 'cfg': config}          # devenv.com is CLI friendly, devenv.exe... not so much.          return ('"%sdevenv.com" %s.sln /build %s' %  diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index c8c4fe0c3c..1e625bcee8 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -139,6 +139,9 @@ public:      /// Get information about a specific Callable      LLSD getMetadata(const std::string& name) const; +    /// Retrieve the LLSD key we use for one-arg <tt>operator()</tt> method +    std::string getDispatchKey() const { return mKey; } +  private:      template <class CLASS, typename METHOD>      void addMethod(const std::string& name, const std::string& desc, diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 45b84ea3ea..f5c90291b8 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -36,6 +36,7 @@  #include "llinstancetracker.h"  #define FAST_TIMER_ON 1 +#define TIME_FAST_TIMERS 0  #if LL_WINDOWS @@ -56,7 +57,7 @@ inline U32 get_cpu_clock_count_32()      return ret_val;  } -// return full timer value, still shifted by 8 bits +// return full timer value, *not* shifted by 8 bits  inline U64 get_cpu_clock_count_64()  {  	U64 ret_val; @@ -69,7 +70,7 @@ inline U64 get_cpu_clock_count_64()  		mov dword ptr [ret_val+4], edx  		mov dword ptr [ret_val], eax  	} -    return ret_val >> 8; +    return ret_val;  }  #endif // LL_WINDOWS @@ -242,6 +243,9 @@ public:  	LLFastTimer(NamedTimer::FrameState& timer)  	:	mFrameState(&timer)  	{ +#if TIME_FAST_TIMERS +		U64 timer_start = get_cpu_clock_count_64(); +#endif  #if FAST_TIMER_ON  		NamedTimer::FrameState* frame_state = &timer;  		U32 cur_time = get_cpu_clock_count_32(); @@ -256,10 +260,17 @@ public:  		mLastTimer = sCurTimer;  		sCurTimer = this;  #endif +#if TIME_FAST_TIMERS +		U64 timer_end = get_cpu_clock_count_64(); +		sTimerCycles += timer_end - timer_start; +#endif  	}  	~LLFastTimer()  	{ +#if TIME_FAST_TIMERS +		U64 timer_start = get_cpu_clock_count_64(); +#endif  #if FAST_TIMER_ON  		NamedTimer::FrameState* frame_state = mFrameState;  		U32 cur_time = get_cpu_clock_count_32(); @@ -276,6 +287,11 @@ public:  		U32 total_time = cur_time - mStartTotalTime;  		last_timer->mStartSelfTime += total_time;  #endif +#if TIME_FAST_TIMERS +		U64 timer_end = get_cpu_clock_count_64(); +		sTimerCycles += timer_end - timer_start; +		sTimerCalls++; +#endif	  	} @@ -297,11 +313,12 @@ public:  	static const NamedTimer* getTimerByName(const std::string& name);  public: -	static bool 		sPauseHistory; -	static bool 		sResetHistory; +	static bool 			sPauseHistory; +	static bool 			sResetHistory; +	static U64				sTimerCycles; +	static U32				sTimerCalls;  private: -	typedef std::vector<LLFastTimer*> timer_stack_t;  	static LLFastTimer*		sCurTimer;  	static S32				sCurFrameIndex;  	static S32				sLastFrameIndex; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 7ad5f9608f..37a28ac721 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -135,7 +135,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons  	S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); -	// determine which style flags need to be added programmatically by striping off the +	// determine which style flags need to be added programmatically by stripping off the  	// style bits that are drawn by the underlying Freetype font  	U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle(); diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 63faf44f9d..6a5b475134 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -54,6 +54,7 @@ void LLDockableFloater::init(LLDockableFloater* thiz)  LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,  		const LLSD& key, const Params& params) :  	LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true) +	, mOverlapsScreenChannel(false)  {  	init(this);  } diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 2c339f4a3f..ae4f99e205 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -50,6 +50,16 @@ public:  	LOG_CLASS(LLDockableFloater);  	LLDockableFloater(LLDockControl* dockControl, const LLSD& key,  			const Params& params = getDefaultParams()); + +	/** +	 * Constructor. +	 * @param dockControl a pointer to the doc control instance +	 * @param uniqueDocking - a flag defines is docking should work as tab(at one +	 * moment only one docked floater can be shown), also this flag defines is dock +	 * tongue should be used. +	 * @params key a floater key. + 	 * @params params a floater parameters +	 */  	LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking,  			const LLSD& key, const Params& params = getDefaultParams());  	virtual ~LLDockableFloater(); @@ -85,6 +95,15 @@ public:  	LLDockControl* getDockControl(); +	/** +	 * Returns true if screen channel should consider floater's size when drawing toasts. +	 * +	 * By default returns false. +	 */ +	virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); } +	virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; } + +	bool getUniqueDocking() { return mUniqueDocking;	}  private:  	/**  	 * Provides unique of dockable floater. @@ -105,6 +124,8 @@ private:  	 *  non exclusively.  	 */  	bool mUniqueDocking; + +	bool mOverlapsScreenChannel;  };  #endif /* LL_DOCKABLEFLOATER_H */ diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index 456a2925a3..1c3c8449c5 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -182,6 +182,14 @@ void LLDockControl::moveDockable()  	LLRect rootRect;  	mGetAllowedRectCallback(rootRect); +	bool unique_docking = false; +	LLDockableFloater* dockable_floater = +			dynamic_cast<LLDockableFloater*> (mDockableFloater); +	if (dockable_floater != NULL) +	{ +		unique_docking = dockable_floater->getUniqueDocking(); +	} +  	LLRect dockableRect = mDockableFloater->calcScreenRect();  	S32 x = 0;  	S32 y = 0; @@ -208,7 +216,13 @@ void LLDockControl::moveDockable()  	case TOP:  		x = dockRect.getCenterX() - dockableRect.getWidth() / 2; -		y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight(); +		y = dockRect.mTop + dockableRect.getHeight(); +		// unique docking used with dock tongue, so add tongue height o the Y coordinate +		if (unique_docking) +		{ +			y += mDockTongue->getHeight(); +		} +  		// check is dockable inside root view rect  		if (x < rootRect.mLeft)  		{ @@ -273,7 +287,15 @@ void LLDockControl::forceRecalculatePosition()  void LLDockControl::drawToungue()  { -	if (mEnabled) +	bool unique_docking = false; +	LLDockableFloater* dockable_floater = +			dynamic_cast<LLDockableFloater*> (mDockableFloater); +	if (dockable_floater != NULL) +	{ +		unique_docking = dockable_floater->getUniqueDocking(); +	} + +	if (mEnabled && unique_docking)  	{  		mDockTongue->draw(mDockTongueX, mDockTongueY);  	} diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 09124c3013..3754d155cf 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -66,7 +66,7 @@ const LLRect& LLFlatListView::getItemsRect() const  	return mItemsPanel->getRect();   } -bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/) +bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/,bool rearrange /*= true*/)  {  	if (!item) return false;  	if (value.isUndefined()) return false; @@ -97,8 +97,11 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*  	// Children don't accept the focus  	item->setTabStop(false); -	rearrangeItems(); -	notifyParentItemsRectChanged(); +	if (rearrange) +	{ +		rearrangeItems(); +		notifyParentItemsRectChanged(); +	}  	return true;  } @@ -560,6 +563,8 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask)  	if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() )  	{ +		ensureSelectedVisible(); +		/*  		LLRect visible_rc = getVisibleContentRect();  		LLRect selected_rc = getLastSelectedItemRect(); @@ -572,7 +577,8 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask)  		// In case we are in accordion tab notify parent to show selected rectangle  		LLRect screen_rc;  		localRectToScreen(selected_rc, &screen_rc); -		notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); +		notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));*/ +  		handled = TRUE;  	} @@ -694,11 +700,30 @@ LLRect LLFlatListView::getSelectedItemsRect()  void LLFlatListView::selectFirstItem	()  {  	selectItemPair(mItemPairs.front(), true); +	ensureSelectedVisible();  }  void LLFlatListView::selectLastItem		()  {  	selectItemPair(mItemPairs.back(), true); +	ensureSelectedVisible(); +} + +void LLFlatListView::ensureSelectedVisible() +{ +	LLRect visible_rc = getVisibleContentRect(); +	LLRect selected_rc = getLastSelectedItemRect(); + +	if ( !visible_rc.contains (selected_rc) ) +	{ +		// But scroll in Items panel coordinates +		scrollToShowRect(selected_rc); +	} + +	// In case we are in accordion tab notify parent to show selected rectangle +	LLRect screen_rc; +	localRectToScreen(selected_rc, &screen_rc); +	notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));  } @@ -958,7 +983,86 @@ S32 LLFlatListView::notify(const LLSD& info)  			return 1;  		}  	} +	else if (info.has("rearrange")) +	{ +		rearrangeItems(); +		notifyParentItemsRectChanged(); +		return 1; +	}  	return 0;  } +void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items) +{ +	LLSD action; +	action.with("detach", LLSD()); +	// Clear detached_items list +	detached_items.clear(); +	// Go through items and detach valid items, remove them from items panel +	// and add to detached_items. +	for (pairs_iterator_t +			 iter = mItemPairs.begin(), +			 iter_end = mItemPairs.end(); +		 iter != iter_end; ++iter) +	{ +		LLPanel* pItem = (*iter)->first; +		if (1 == pItem->notify(action)) +		{ +			selectItemPair((*iter), false); +			mItemsPanel->removeChild(pItem); +			detached_items.push_back(pItem); +		} +	} +	if (!detached_items.empty()) +	{ +		// Some items were detached, clean ourself from unusable memory +		if (detached_items.size() == mItemPairs.size()) +		{ +			// This way will be faster if all items were disconnected +			for (pairs_iterator_t +					 iter = mItemPairs.begin(), +					 iter_end = mItemPairs.end(); +				 iter != iter_end; ++iter) +			{ +				(*iter)->first = NULL; +				delete *iter; +			} +			mItemPairs.clear(); +			// Also set items panel height to zero. +			// Reshape it to allow reshaping of non-item children. +			LLRect rc = mItemsPanel->getRect(); +			rc.mBottom = rc.mTop; +			mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); +			mItemsPanel->setRect(rc); +			setNoItemsCommentVisible(true); +		} +		else +		{ +			for (std::vector<LLPanel*>::const_iterator +					 detached_iter = detached_items.begin(), +					 detached_iter_end = detached_items.end(); +				 detached_iter != detached_iter_end; ++detached_iter) +			{ +				LLPanel* pDetachedItem = *detached_iter; +				for (pairs_iterator_t +						 iter = mItemPairs.begin(), +						 iter_end = mItemPairs.end(); +					 iter != iter_end; ++iter) +				{ +					item_pair_t* item_pair = *iter; +					if (item_pair->first == pDetachedItem) +					{ +						mItemPairs.erase(iter); +						item_pair->first = NULL; +						delete item_pair; +						break; +					} +				} +			} +			rearrangeItems(); +		} +		notifyParentItemsRectChanged(); +	} +} +  //EOF diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index ba824ff2df..5999e79f61 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -124,6 +124,8 @@ public:  	/** Returns full rect of child panel */  	const LLRect& getItemsRect() const; +	LLRect getRequiredRect() { return getItemsRect(); } +  	/** Returns distance between items */  	const S32 getItemsPad() { return mItemPad; } @@ -131,7 +133,7 @@ public:  	 * Adds and item and LLSD value associated with it to the list at specified position  	 * @return true if the item was added, false otherwise   	 */ -	virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM); +	virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM, bool rearrange = true);  	/**  	 * Insert item_to_add along with associated value to the list right after the after_item. @@ -269,6 +271,15 @@ public:  	virtual void clear();  	/** +	 * Removes all items that can be detached from the list but doesn't destroy +	 * them, caller responsible to manage items after they are detached. +	 * Detachable item should accept "detach" action via notify() method, +	 * where it disconnect all callbacks, does other valuable routines and +	 * return 1. +	 */ +	void detachItems(std::vector<LLPanel*>& detached_items); + +	/**  	 * Set comparator to use for future sorts.  	 *   	 * This class does NOT manage lifetime of the comparator @@ -359,6 +370,8 @@ protected:  	LLRect getSelectedItemsRect(); +	void   ensureSelectedVisible(); +  private:  	void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;} diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index f7fd2dbdfe..845203b420 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2148,6 +2148,11 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)  	if (give_focus && !gFocusMgr.childHasKeyboardFocus(child))  	{  		child->setFocus(TRUE); +		// floater did not take focus, so relinquish focus to world +		if (!child->hasFocus()) +		{ +			gFocusMgr.setKeyboardFocus(NULL); +		}  	}  } @@ -2717,7 +2722,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o  	}  	params.from_xui = true; -	setupParams(params, parent); +	applyXUILayout(params, parent);   	initFromParams(params);  	initFloater(params); diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 5e15fa3919..1aaba88c49 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -247,7 +247,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o  	}  	p.from_xui = true; -	setupParams(p, parent); +	applyXUILayout(p, parent);  	LLLayoutStack* layout_stackp = LLUICtrlFactory::create<LLLayoutStack>(p);  	if (parent && layout_stackp) @@ -414,6 +414,16 @@ void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL au  	}  } +void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize) +{ +	LayoutPanel* panel = findEmbeddedPanelByName(panel_name); + +	if (panel) +	{ +		panel->mUserResize = user_resize; +	} +} +  bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp)  {  	LayoutPanel* panel = findEmbeddedPanelByName(panel_name); diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index c1af428674..cde383b047 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -80,6 +80,7 @@ public:  	S32 getNumPanels() { return mPanels.size(); }  	void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize); +	void setPanelUserResize(const std::string& panel_name, BOOL user_resize);  	/**  	 * Gets minimal width and/or height of the specified by name panel. diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 202ed04fbc..60ef01074b 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3610,6 +3610,11 @@ public:  	LLContextMenuBranch(const Params&); +	virtual ~LLContextMenuBranch() +	{ +		delete mBranch; +	} +  	// called to rebuild the draw label  	virtual void	buildDrawLabel( void ); diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index 1891bca36c..aea7c5f87c 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -50,6 +50,12 @@ const F32 FLOAT_THRESHOLD = 0.00001f;  S32 LLMultiSlider::mNameCounter = 0; +LLMultiSlider::SliderParams::SliderParams() +:	name("name"), +	value("value", 0.f) +{ +} +  LLMultiSlider::Params::Params()  :	max_sliders("max_sliders", 1),  	allow_overlap("allow_overlap", false), @@ -63,7 +69,8 @@ LLMultiSlider::Params::Params()  	triangle_color("triangle_color"),  	mouse_down_callback("mouse_down_callback"),  	mouse_up_callback("mouse_up_callback"), -	thumb_width("thumb_width") +	thumb_width("thumb_width"), +	sliders("slider")  {  	name = "multi_slider_bar";  	mouse_opaque(true); @@ -99,6 +106,20 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)  	{  		setMouseUpCallback(initCommitCallback(p.mouse_up_callback));  	} + +	for (LLInitParam::ParamIterator<SliderParams>::const_iterator it = p.sliders().begin(); +		it != p.sliders().end(); +		++it) +	{ +		if (it->name.isProvided()) +		{ +			addSlider(it->value, it->name); +		} +		else +		{ +			addSlider(it->value); +		} +	}  }  LLMultiSlider::~LLMultiSlider() @@ -230,6 +251,30 @@ const std::string& LLMultiSlider::addSlider(F32 val)  	return mCurSlider;  } +void LLMultiSlider::addSlider(F32 val, const std::string& name) +{ +	F32 initVal = val; + +	if(mValue.size() >= mMaxNumSliders) { +		return; +	} + +	bool foundOne = findUnusedValue(initVal); +	if(!foundOne) { +		return; +	} + +	// add a new thumb rect +	mThumbRects[name] = LLRect( 0, getRect().getHeight(), mThumbWidth, 0 ); + +	// add the value and set the current slider to this one +	mValue.insert(name, initVal); +	mCurSlider = name; + +	// move the slider +	setSliderValue(mCurSlider, initVal, TRUE); +} +  bool LLMultiSlider::findUnusedValue(F32& initVal)  {  	bool firstTry = true; @@ -572,7 +617,6 @@ void LLMultiSlider::draw()  	LLF32UICtrl::draw();  } -  boost::signals2::connection LLMultiSlider::setMouseDownCallback( const commit_signal_t::slot_type& cb )   {   	if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h index f8e43a0470..88576da85b 100644 --- a/indra/llui/llmultislider.h +++ b/indra/llui/llmultislider.h @@ -41,6 +41,13 @@ class LLUICtrlFactory;  class LLMultiSlider : public LLF32UICtrl  {  public: +	struct SliderParams : public LLInitParam::Block<SliderParams> +	{ +		Optional<std::string>	name; +		Mandatory<F32>			value; +		SliderParams(); +	}; +  	struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params>  	{  		Optional<S32>	max_sliders; @@ -60,6 +67,7 @@ public:  										mouse_up_callback;  		Optional<S32>		thumb_width; +		Multiple<SliderParams>	sliders;  		Params();  	}; @@ -68,13 +76,13 @@ protected:  	friend class LLUICtrlFactory;  public:  	virtual ~LLMultiSlider(); -	void			setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE); -	F32				getSliderValue(const std::string& name) const; +	void				setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE); +	F32					getSliderValue(const std::string& name) const; -	const std::string& getCurSlider() const					{ return mCurSlider; } -	F32				getCurSliderValue() const				{ return getSliderValue(mCurSlider); } -	void			setCurSlider(const std::string& name); -	void			setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); } +	const std::string&	getCurSlider() const					{ return mCurSlider; } +	F32					getCurSliderValue() const				{ return getSliderValue(mCurSlider); } +	void				setCurSlider(const std::string& name); +	void				setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); }  	/*virtual*/ void	setValue(const LLSD& value);  	/*virtual*/ LLSD	getValue() const		{ return mValue; } @@ -82,12 +90,13 @@ public:  	boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb );  	boost::signals2::connection setMouseUpCallback(	const commit_signal_t::slot_type& cb ); -	bool			findUnusedValue(F32& initVal); +	bool				findUnusedValue(F32& initVal);  	const std::string&	addSlider();  	const std::string&	addSlider(F32 val); -	void			deleteSlider(const std::string& name); -	void			deleteCurSlider()			{ deleteSlider(mCurSlider); } -	void			clear(); +	void				addSlider(F32 val, const std::string& name); +	void				deleteSlider(const std::string& name); +	void				deleteCurSlider()			{ deleteSlider(mCurSlider); } +	void				clear();  	/*virtual*/ BOOL	handleHover(S32 x, S32 y, MASK mask);  	/*virtual*/ BOOL	handleMouseUp(S32 x, S32 y, MASK mask); @@ -109,7 +118,8 @@ protected:  	LLRect			mDragStartThumbRect;  	S32				mThumbWidth; -	std::map<std::string, LLRect>	mThumbRects; +	std::map<std::string, LLRect>	 +					mThumbRects;  	LLUIColor		mTrackColor;  	LLUIColor		mThumbOutlineColor;  	LLUIColor		mThumbCenterColor; diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index 7323323d8c..f4434a0f78 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -65,7 +65,8 @@ LLMultiSliderCtrl::Params::Params()  	text_color("text_color"),  	text_disabled_color("text_disabled_color"),  	mouse_down_callback("mouse_down_callback"), -	mouse_up_callback("mouse_up_callback") +	mouse_up_callback("mouse_up_callback"), +	sliders("slider")  {  	mouse_opaque = true;  } @@ -161,6 +162,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)  	S32 slider_left = label_width ? label_width + multi_sliderctrl_spacing : 0;  	LLRect slider_rect( slider_left, top, slider_right, bottom );  	LLMultiSlider::Params params; +	params.sliders = p.sliders;  	params.rect(slider_rect);  	params.commit_callback.function( LLMultiSliderCtrl::onSliderCommit );  	params.mouse_down_callback( p.mouse_down_callback ); diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index 16d07541f2..e8366d09c2 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -69,6 +69,8 @@ public:  		Optional<CommitCallbackParam>	mouse_down_callback,  										mouse_up_callback; +		Multiple<LLMultiSlider::SliderParams>	sliders; +  		Params();  	}; diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index 629964c322..ee6ec0f88f 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -188,9 +188,10 @@ public:          LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel));          if (channelptr)          { -            // Try connecting at the front of the 'changed' signal. That way -            // we shouldn't get starved by preceding listeners. -            channelptr->connectAtFrontChanged(boost::bind(&Forwarder::handle, this, _1)); +            // Insert our processing as a "passed filter" listener. This way +            // we get to run before all the "changed" listeners, and we get to +            // swipe it (hide it from the other listeners) if desired. +            channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1));          }      } @@ -251,6 +252,7 @@ bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const      if (notification["sigtype"].asString() == "delete")      {          LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL; +        // let other listeners see the "delete" operation          return false;      }      LLNotificationPtr note(mNotifications.find(notification["id"])); @@ -262,6 +264,8 @@ bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const      if (! matchType(mTypes, note->getType()))      {          LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL; +        // We're not supposed to intercept this particular notification. Let +        // other listeners process it.          return false;      }      LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL; @@ -282,7 +286,11 @@ bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const              mNotifications.cancel(note);          }      } -    return false;                   // let other listeners get same notification +    // If we've auto-responded to this notification, then it's going to be +    // deleted. Other listeners would get the change operation, try to look it +    // up and be baffled by lookup failure. So when we auto-respond, suppress +    // this notification: don't pass it to other listeners. +    return mRespond;  }  bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const @@ -314,7 +322,7 @@ bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std  LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note)  {      LLSD notificationInfo(note->asLLSD()); -    // For some reason the following aren't included in asLLSD(). +    // For some reason the following aren't included in LLNotification::asLLSD().      notificationInfo["summary"] = note->summarize();      notificationInfo["id"]      = note->id();      notificationInfo["type"]    = note->getType(); diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 738a96f730..db32882438 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -452,7 +452,7 @@ void LLPanel::initFromParams(const LLPanel::Params& p)  	parseFollowsFlags(p);  	setToolTip(p.tool_tip()); -	setSaveToXML(p.from_xui); +	setFromXUI(p.from_xui);  	mHoverCursor = getCursorFromString(p.hover_cursor); @@ -542,7 +542,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu  		}  		params.from_xui = true; -		setupParams(params, parent); +		applyXUILayout(params, parent);  		{  			LLFastTimer timer(FTM_PANEL_CONSTRUCTION);  			initFromParams(params); diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index 997b9c13f8..4087b484aa 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -116,6 +116,10 @@ void LLRadioGroup::initFromParams(const Params& p)  		item_params.font.setIfNotProvided(mFont); // apply radio group font by default  		item_params.commit_callback.function = boost::bind(&LLRadioGroup::onClickButton, this, _1);  		item_params.from_xui = p.from_xui; +		if (p.from_xui) +		{ +			applyXUILayout(item_params, this); +		}  		LLRadioCtrl* item = LLUICtrlFactory::create<LLRadioCtrl>(item_params, this);  		mRadioButtons.push_back(item); diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 544352176a..7238d903a3 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -353,7 +353,7 @@ LLScrollListCheck::LLScrollListCheck(const LLScrollListCell::Params& p)  {  	LLCheckBoxCtrl::Params checkbox_p;  	checkbox_p.name("checkbox"); -	checkbox_p.rect.left(0).bottom(0).width(p.width).height(p.width); +	checkbox_p.rect = LLRect(0, p.width, p.width, 0);  	checkbox_p.enabled(p.enabled);  	checkbox_p.initial_value(p.value()); diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index d6d46654d5..20a1ab7af3 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -75,10 +75,8 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)  	static LLUICachedControl<S32> spinctrl_spacing ("UISpinctrlSpacing", 0);  	static LLUICachedControl<S32> spinctrl_btn_width ("UISpinctrlBtnWidth", 0);  	static LLUICachedControl<S32> spinctrl_btn_height ("UISpinctrlBtnHeight", 0); -	S32 top = getRect().getHeight(); -	S32 bottom = top - 2 * spinctrl_btn_height; -	S32 centered_top = top; -	S32 centered_bottom = bottom; +	S32 centered_top = getRect().getHeight(); +	S32 centered_bottom = getRect().getHeight() - 2 * spinctrl_btn_height;  	S32 btn_left = 0;  	// reserve space for spinner  	S32 label_width = llclamp(p.label_width(), 0, llmax(0, getRect().getWidth() - 40)); @@ -105,25 +103,15 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)  	// Spin buttons  	LLButton::Params up_button_params(p.up_button); -	up_button_params.rect -					.left(btn_left) -					.top(top) -					.right(btn_right) -					.height(spinctrl_btn_height); +	up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height);  	up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));  	up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));  	mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params);  	addChild(mUpBtn); -	LLRect down_rect( btn_left, top - spinctrl_btn_height, btn_right, bottom ); -  	LLButton::Params down_button_params(p.down_button); -	down_button_params.rect -					.left(btn_left) -					.right(btn_right) -					.bottom(bottom) -					.height(spinctrl_btn_height); +	down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height);  	down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));  	down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));  	mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 83e2e3db50..327dd01612 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -266,8 +266,6 @@ bool LLTabContainer::addChild(LLView* view, S32 tab_group)  	if (panelp)  	{ -		panelp->setSaveToXML(TRUE); -  		addTabPanel(TabPanelParams().panel(panelp).label(panelp->getLabel()).is_placeholder(dynamic_cast<LLPlaceHolderPanel*>(view) != NULL));  		return true;  	} @@ -1019,12 +1017,10 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)  	{  		if (textbox)  		{ -			textbox->setSaveToXML(false);  			addChild( textbox, 0 );  		}  		if (btn)  		{ -			btn->setSaveToXML(false);  			addChild( btn, 0 );  		}  	} @@ -1747,24 +1743,20 @@ void LLTabContainer::initButtons()  		}  	} -	mPrevArrowBtn->setSaveToXML(false);  	mPrevArrowBtn->setTabStop(FALSE);  	addChild(mPrevArrowBtn); -	mNextArrowBtn->setSaveToXML(false);  	mNextArrowBtn->setTabStop(FALSE);  	addChild(mNextArrowBtn);  	if (mJumpPrevArrowBtn)  	{ -		mJumpPrevArrowBtn->setSaveToXML(false);  		mJumpPrevArrowBtn->setTabStop(FALSE);  		addChild(mJumpPrevArrowBtn);  	}  	if (mJumpNextArrowBtn)  	{ -		mJumpNextArrowBtn->setSaveToXML(false);  		mJumpNextArrowBtn->setTabStop(FALSE);  		addChild(mJumpNextArrowBtn);  	} diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index cb0907a771..7447a984ac 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -842,7 +842,7 @@ BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask)  	{  		// Did we just click on a link?  		if (cur_segment->getStyle() -			&& cur_segment->getStyle()->isLink()) +		    && cur_segment->getStyle()->isLink())  		{  			// *TODO: send URL here?  			mURLClickSignal(this, LLSD() ); @@ -962,7 +962,10 @@ void LLTextBase::draw()  	reflow();  	// then update scroll position, as cursor may have moved -	updateScrollFromCursor(); +	if (!mReadOnly) +	{ +		updateScrollFromCursor(); +	}  	LLRect doc_rect;  	if (mScroller) @@ -1474,7 +1477,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)  	}  } -void LLTextBase::setText(const LLStringExplicit &utf8str ,const LLStyle::Params& input_params) +void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)  {  	// clear out the existing text and segments  	getViewModel()->setDisplay(LLWStringUtil::null); @@ -1932,11 +1935,19 @@ void LLTextBase::endOfLine()  void LLTextBase::startOfDoc()  {  	setCursorPos(0); +	if (mScroller) +	{ +		mScroller->goToTop(); +	}  }  void LLTextBase::endOfDoc()  {  	setCursorPos(getLength()); +	if (mScroller) +	{ +		mScroller->goToBottom(); +	}  }  void LLTextBase::changePage( S32 delta ) @@ -2001,6 +2012,16 @@ void LLTextBase::changeLine( S32 delta )  	setCursorPos(new_cursor_pos, true);  } +bool LLTextBase::scrolledToStart() +{ +	return mScroller->isAtTop(); +} + +bool LLTextBase::scrolledToEnd() +{ +	return mScroller->isAtBottom(); +} +  bool LLTextBase::setCursor(S32 row, S32 column)  { @@ -2299,14 +2320,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele  		S32 end = llmin( selection_start, seg_end );  		S32 length =  end - start;  		font->render(text, start,  -					rect.mLeft, rect.mTop,  -					color,  -					LLFontGL::LEFT, LLFontGL::TOP,  -					0,  -					mStyle->getShadowType(),  -					length, rect.getWidth(),  -					&right_x,  -					mEditor.getUseEllipses()); +			     rect.mLeft, rect.mTop,  +			     color,  +			     LLFontGL::LEFT, LLFontGL::TOP,  +			     LLFontGL::NORMAL,  +			     mStyle->getShadowType(),  +			     length, rect.getWidth(),  +			     &right_x,  +			     mEditor.getUseEllipses());  	}  	rect.mLeft = (S32)ceil(right_x); @@ -2318,14 +2339,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele  		S32 length = end - start;  		font->render(text, start,  -					rect.mLeft, rect.mTop, -					LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), -					LLFontGL::LEFT, LLFontGL::TOP,  -					0,  -					LLFontGL::NO_SHADOW,  -					length, rect.getWidth(),  -					&right_x,  -					mEditor.getUseEllipses()); +			     rect.mLeft, rect.mTop, +			     LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), +			     LLFontGL::LEFT, LLFontGL::TOP,  +			     LLFontGL::NORMAL,  +			     LLFontGL::NO_SHADOW,  +			     length, rect.getWidth(),  +			     &right_x,  +			     mEditor.getUseEllipses());  	}  	rect.mLeft = (S32)ceil(right_x);  	if( selection_end < seg_end ) @@ -2335,14 +2356,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele  		S32 end = seg_end;  		S32 length = end - start;  		font->render(text, start,  -					rect.mLeft, rect.mTop,  -					color,  -					LLFontGL::LEFT, LLFontGL::TOP,  -					0,  -					mStyle->getShadowType(),  -					length, rect.getWidth(),  -					&right_x,  -					mEditor.getUseEllipses()); +			     rect.mLeft, rect.mTop,  +			     color,  +			     LLFontGL::LEFT, LLFontGL::TOP,  +			     LLFontGL::NORMAL,  +			     mStyle->getShadowType(),  +			     length, rect.getWidth(),  +			     &right_x,  +			     mEditor.getUseEllipses());  	}  	return right_x;  } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index a1f8ba39ae..038b9eaa62 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -180,8 +180,11 @@ public:  	void					changePage( S32 delta );  	void					changeLine( S32 delta ); +	bool					scrolledToStart(); +	bool					scrolledToEnd();  	const LLFontGL*			getDefaultFont() const					{ return mDefaultFont; } +	LLStyle::Params			getDefaultStyle();  public:  	// Fired when a URL link is clicked @@ -254,7 +257,6 @@ protected:  	LLTextBase(const Params &p);  	virtual ~LLTextBase();  	void							initFromParams(const Params& p); -	LLStyle::Params					getDefaultStyle();  	virtual void					onValueChange(S32 start, S32 end);  	// draw methods diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 1ea6b66a93..d0ed3b6fca 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1915,6 +1915,7 @@ namespace LLInitParam  		green = color.mV[VGREEN];  		blue = color.mV[VBLUE];  		alpha = color.mV[VALPHA]; +		control.set("", false);  	}  	void TypeValues<LLUIColor>::declareValues() @@ -2046,12 +2047,16 @@ namespace LLInitParam  	void TypedParam<LLRect>::setBlockFromValue()  	{ -		left = mData.mValue.mLeft; -		right = mData.mValue.mRight; -		bottom = mData.mValue.mBottom; -		top = mData.mValue.mTop; -		width.setProvided(false); -		height.setProvided(false); +		// because of the ambiguity in specifying a rect by position and/or dimensions +		// we clear the "provided" flag so that values from xui/etc have priority +		// over those calculated from the rect object + +		left.set(mData.mValue.mLeft, false); +		right.set(mData.mValue.mRight, false); +		bottom.set(mData.mValue.mBottom, false); +		top.set(mData.mValue.mTop, false); +		width.set(mData.mValue.getWidth(), false); +		height.set(mData.mValue.getHeight(), false);  	}  	TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 6788f29ba9..b1fa6add67 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -184,8 +184,6 @@ public:  	{  		T* widget = NULL; -		T::setupParams(params, parent); -  		if (!params.validateBlock())  		{  			llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl; @@ -310,6 +308,7 @@ fail:  		// Apply layout transformations, usually munging rect  		params.from_xui = true; +		T::applyXUILayout(params, parent);  		T* widget = createWidget<T>(params, parent);  		typedef typename T::child_registry_t registry_t; diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index 1dfc281d93..966d919dc7 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -168,6 +168,7 @@ namespace LLInitParam  		if (name() == "none")  		{  			mData.mValue = NULL; +			return;  		}  		LLUIImage* imagep =  LLUI::getUIImage(name()); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 7350457274..983f0a2d49 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -80,7 +80,7 @@ std::string LLUrlEntryBase::escapeUrl(const std::string &url) const  			"ABCDEFGHIJKLMNOPQRSTUVWXYZ"  			"abcdefghijklmnopqrstuvwxyz"  			"0123456789" -			"-._~!$?&()*+,@:;=/%"; +			"-._~!$?&()*+,@:;=/%#";  		std::sort(no_escape_chars.begin(), no_escape_chars.end());  		initialized = true; @@ -201,7 +201,7 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string)  //  LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()  { -	mPattern = boost::regex("(\\bwww\\.\\S+\\.\\S+|\\S+.com\\S*|\\S+.net\\S*|\\S+.edu\\S*|\\S+.org\\S*)", +	mPattern = boost::regex("(\\bwww\\.\\S+\\.\\S+|\\b[^ \t\n\r\f\v:/]+.com\\S*|\\b[^ \t\n\r\f\v:/]+.net\\S*|\\b[^ \t\n\r\f\v:/]+.edu\\S*|\\b[^ \t\n\r\f\v:/]+.org\\S*)",  							boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_http.xml";  	mTooltip = LLTrans::getString("TooltipHttpUrl"); diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index afcff0d409..ad5c0911f8 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -223,3 +223,23 @@ bool LLUrlRegistry::hasUrl(const LLWString &text)  	LLUrlMatch match;  	return findUrl(text, match);  } + +bool LLUrlRegistry::isUrl(const std::string &text) +{ +	LLUrlMatch match; +	if (findUrl(text, match)) +	{ +		return (match.getStart() == 0 && match.getEnd() >= text.size()-1); +	} +	return false; +} + +bool LLUrlRegistry::isUrl(const LLWString &text) +{ +	LLUrlMatch match; +	if (findUrl(text, match)) +	{ +		return (match.getStart() == 0 && match.getEnd() >= text.size()-1); +	} +	return false; +} diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index d7800d8cfc..399ee0a988 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -85,6 +85,10 @@ public:  	bool hasUrl(const std::string &text);  	bool hasUrl(const LLWString &text); +	// return true if the given string is a URL that findUrl would match +	bool isUrl(const std::string &text); +	bool isUrl(const LLWString &text); +  private:  	LLUrlRegistry();  	friend class LLSingleton<LLUrlRegistry>; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index a8d8626e49..f1b08c380b 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -126,7 +126,7 @@ LLView::LLView(const LLView::Params& p)  :	mName(p.name),  	mParentView(NULL),  	mReshapeFlags(FOLLOWS_NONE), -	mSaveToXML(p.from_xui), +	mFromXUI(p.from_xui),  	mIsFocusRoot(FALSE),  	mLastVisible(FALSE),  	mNextInsertionOrdinal(0), @@ -2479,7 +2479,7 @@ static bool get_last_child_rect(LLView* parent, LLRect *rect)  	for (;itor != parent->getChildList()->end(); ++itor)  	{  		LLView *last_view = (*itor); -		if (last_view->getSaveToXML()) +		if (last_view->getFromXUI())  		{  			*rect = last_view->getRect();  			return true; @@ -2489,7 +2489,7 @@ static bool get_last_child_rect(LLView* parent, LLRect *rect)  }  //static -void LLView::setupParams(LLView::Params& p, LLView* parent) +void LLView::applyXUILayout(LLView::Params& p, LLView* parent)  {  	const S32 VPAD = 4;  	const S32 MIN_WIDGET_HEIGHT = 10; @@ -2509,7 +2509,7 @@ void LLView::setupParams(LLView::Params& p, LLView* parent)  		LLRect last_rect = parent->getLocalRect();  		bool layout_topleft = (p.layout() == "topleft"); -		if (layout_topleft && p.from_xui) +		if (layout_topleft)  		{  			//invert top to bottom  			if (p.rect.top.isProvided()) p.rect.top = parent_rect.getHeight() - p.rect.top; @@ -2535,10 +2535,10 @@ void LLView::setupParams(LLView::Params& p, LLView* parent)  				p.rect.right.setProvided(false); // recalculate the right  			}  		} -		else if (p.from_xui) // only do negative coordinate magic for XUI +		else  		{ -			if (p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); -			if (p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth(); +			if (p.rect.left.isProvided() && p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); +			if (p.rect.right.isProvided() && p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth();  		}  		if (p.center_vert)  		{ @@ -2556,15 +2556,15 @@ void LLView::setupParams(LLView::Params& p, LLView* parent)  				p.rect.top.setProvided(false); // recalculate the top  			}  		} -		else if (p.from_xui) +		else  		{ -			if (p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); -			if (p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight(); +			if (p.rect.bottom.isProvided() && p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); +			if (p.rect.top.isProvided() && p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight();  		}  		// DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels -		if (!p.rect.height.isProvided() && !p.rect.top.isProvided()) +		if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0)  		{  			p.rect.height = MIN_WIDGET_HEIGHT;  		} @@ -2663,7 +2663,7 @@ static void convert_to_relative_layout(LLView::Params& p, LLView* parent)  	// Use setupParams to get the final widget rectangle  	// according to our wacky layout rules.  	LLView::Params final = p; -	LLView::setupParams(final, parent); +	LLView::applyXUILayout(final, parent);  	// Must actually extract the rectangle to get consistent  	// right = left+width, top = bottom+height  	LLRect final_rect = final.rect; diff --git a/indra/llui/llview.h b/indra/llui/llview.h index f8460f5361..c4d7313743 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -395,8 +395,8 @@ public:  	void parseFollowsFlags(const LLView::Params& params);  	// Some widgets, like close box buttons, don't need to be saved -	BOOL getSaveToXML() const { return mSaveToXML; } -	void setSaveToXML(BOOL b) { mSaveToXML = b; } +	BOOL getFromXUI() const { return mFromXUI; } +	void setFromXUI(BOOL b) { mFromXUI = b; }  	typedef enum e_hit_test_type  	{ @@ -498,7 +498,7 @@ public:  	// Set up params after XML load before calling new(),  	// usually to adjust layout. -	static void setupParams(Params& p, LLView* parent); +	static void applyXUILayout(Params& p, LLView* parent);  	// For re-export of floaters and panels, convert the coordinate system  	// to be top-left based. @@ -573,7 +573,7 @@ private:  	LLUIString	mToolTipMsg;	// isNull() is true if none.  	U8          mSoundFlags; -	BOOL		mSaveToXML; +	BOOL		mFromXUI;  	BOOL		mIsFocusRoot;  	BOOL		mUseBoundingRect; // hit test against bounding rectangle that includes all child elements diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp index 109e20f179..484948bd9f 100644 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -108,7 +108,7 @@ gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)  	slvideo = GST_SLVIDEO(bsink); -	DEBUGMSG("\n\ntransferring a frame of %dx%d <- %p (%d)\n\n", +	DEBUGMSG("transferring a frame of %dx%d <- %p (%d)",  		 slvideo->width, slvideo->height, GST_BUFFER_DATA(buf),  		 slvideo->format); @@ -336,7 +336,7 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,  #define MAXDEPTHHACK 4  	GST_OBJECT_LOCK(slvideo); -	if (slvideo->resize_forced) +	if (slvideo->resize_forced_always) // app is giving us a fixed size to work with  	{  		gint slwantwidth, slwantheight;  		slwantwidth = slvideo->resize_try_width; @@ -385,6 +385,8 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,  		}  	} +	GST_OBJECT_UNLOCK(slvideo); +  	if (!made_bufferdata_ptr) // need to fallback to malloc at original size  	{  		GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; @@ -393,8 +395,6 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,  		llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);  	} -	GST_OBJECT_UNLOCK(slvideo); -  	*buf = GST_BUFFER_CAST(newbuf);  	return GST_FLOW_OK; @@ -458,7 +458,7 @@ gst_slvideo_init (GstSLVideo * filter,  	filter->retained_frame_format = SLV_PF_UNKNOWN;  	GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS);  	llgst_caps_replace (&filter->caps, caps); -	filter->resize_forced = false; +	filter->resize_forced_always = false;  	filter->resize_try_width = -1;  	filter->resize_try_height = -1;  	GST_OBJECT_UNLOCK(filter); @@ -499,7 +499,7 @@ gst_slvideo_get_property (GObject * object, guint prop_id,  static gboolean  plugin_init (GstPlugin * plugin)  { -	DEBUGMSG("\n\n\nPLUGIN INIT\n\n\n"); +	DEBUGMSG("PLUGIN INIT");  	GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin",  				 0, (gchar*)"Second Life Video Sink"); @@ -527,7 +527,7 @@ void gst_slvideo_init_class (void)  				  "http://www.secondlife.com/");  #undef PACKAGE  	ll_gst_plugin_register_static (&gst_plugin_desc); -	DEBUGMSG("\n\n\nCLASS INIT\n\n\n"); +	DEBUGMSG("CLASS INIT");  }  #endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h index 208523e8d0..8f1cf84978 100644 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h +++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h @@ -90,7 +90,7 @@ struct _GstSLVideo  	int retained_frame_width, retained_frame_height;  	SLVPixelFormat retained_frame_format;  	// sticky resize info -	bool resize_forced; +	bool resize_forced_always;  	int resize_try_width;  	int resize_try_height;  }; diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp index 8e850ed7ff..26173314a7 100644 --- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -105,7 +105,7 @@ private:          void mouseUp( int x, int y );          void mouseMove( int x, int y ); -        bool sizeChanged(); +        void sizeChanged();  	static bool mDoneInit; @@ -477,9 +477,8 @@ MediaPluginGStreamer010::update(int milliseconds)  			    mCurrentWidth <= mWidth &&  			    !mTextureSegmentName.empty())  			{ -				  				// we're gonna totally consume this frame - reset 'ready' flag -				mVideoSink->retained_frame_ready = FALSE;				 +				mVideoSink->retained_frame_ready = FALSE;  				int destination_rowbytes = mWidth * mDepth;  				for (int row=0; row<mCurrentHeight; ++row)  				{ @@ -840,7 +839,7 @@ MediaPluginGStreamer010::startup()  } -bool +void  MediaPluginGStreamer010::sizeChanged()  {  	// the shared writing space has possibly changed size/location/whatever @@ -855,8 +854,9 @@ MediaPluginGStreamer010::sizeChanged()  			 mNaturalWidth, mNaturalHeight);  	} +	// if the size has changed then the shm has changed and the app needs telling  	if (mCurrentWidth != mPreviousWidth || -	    mCurrentHeight != mPreviousHeight) // if the size has changed then the shm has changed and the app needs telling +	    mCurrentHeight != mPreviousHeight)  	{  		mPreviousWidth = mCurrentWidth;  		mPreviousHeight = mCurrentHeight; @@ -865,11 +865,9 @@ MediaPluginGStreamer010::sizeChanged()  		message.setValue("name", mTextureSegmentName);  		message.setValueS32("width", mNaturalWidth);  		message.setValueS32("height", mNaturalHeight); -		DEBUGMSG("<--- Sending size change request to application with name: '%s' - size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); +		DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight);  		sendMessage(message);  	} -	 -	return true;  } @@ -1000,7 +998,6 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)  				INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress);  				mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); -  			}  			else if(message_name == "shm_remove")  			{ @@ -1079,7 +1076,7 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)  							INFOMSG("**** = REAL RESIZE REQUEST FROM APP");  							GST_OBJECT_LOCK(mVideoSink); -							mVideoSink->resize_forced = true; +							mVideoSink->resize_forced_always = true;  							mVideoSink->resize_try_width = texture_width;  							mVideoSink->resize_try_height = texture_height;  							GST_OBJECT_UNLOCK(mVideoSink); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9f7b782320..a26aae3590 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -258,7 +258,6 @@ set(viewer_SOURCE_FILES      llinventorymodel.cpp      llinventoryobserver.cpp      llinventorypanel.cpp -    llinventorysubtreepanel.cpp      lljoystickbutton.cpp      lllandmarkactions.cpp      lllandmarklist.cpp @@ -354,6 +353,7 @@ set(viewer_SOURCE_FILES      llparticipantlist.cpp      llpatchvertexarray.cpp      llplacesinventorybridge.cpp +    llplacesinventorypanel.cpp      llpolymesh.cpp      llpolymorph.cpp      llpreview.cpp @@ -766,7 +766,6 @@ set(viewer_HEADER_FILES      llinventorymodel.h      llinventoryobserver.h      llinventorypanel.h -    llinventorysubtreepanel.h      lljoystickbutton.h      lllandmarkactions.h      lllandmarklist.h @@ -858,6 +857,7 @@ set(viewer_HEADER_FILES      llparticipantlist.h      llpatchvertexarray.h      llplacesinventorybridge.h +    llplacesinventorypanel.h      llpolymesh.h      llpolymorph.h      llpreview.h @@ -1397,12 +1397,29 @@ if (WINDOWS)      # be met. I'm looking forward to a source-code split-up project next year that will address this kind of thing.      # In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py      # and have the build deps get tracked *please* tell me about it. + +    if(LLKDU_LIBRARY) +      # Configure a var for llkdu which may not exist for all builds. +      set(LLKDU_DLL_SOURCE ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llkdu.dll) +    endif(LLKDU_LIBRARY) + +    if(USE_GOOGLE_PERFTOOLS) +      # Configure a var for tcmalloc location, if used. +      # Note the need to specify multiple names explicitly. +      set(GOOGLE_PERF_TOOLS_SOURCE +        ${SHARED_LIB_STAGING_DIR}/Release/libtcmalloc_minimal.dll +	${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll +	${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll +	) +    endif(USE_GOOGLE_PERFTOOLS) +	   +      set(COPY_INPUT_DEPENDECIES        # The following commented dependencies are determined at variably at build time. Can't do this here. -      #llkdu.dll => llkdu.dll        #${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll        ${CMAKE_SOURCE_DIR}/../etc/message.xml        ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg +      ${LLKDU_DLL_SOURCE}        ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll        ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapr-1.dll        ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libaprutil-1.dll @@ -1426,6 +1443,7 @@ if (WINDOWS)        ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/zlib1.dll        ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxplatform.dll        ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxoal.dll +      ${GOOGLE_PERF_TOOLS_SOURCE}        ${CMAKE_CURRENT_SOURCE_DIR}/licenses-win32.txt        ${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt        ${CMAKE_CURRENT_SOURCE_DIR}/dbghelp.dll @@ -1446,6 +1464,10 @@ if (WINDOWS)        ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qmng4.dll        ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qsvg4.dll        ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qtiff4.dll +      ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecs4.dll +      ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecs4.dll +      ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecs4.dll +      ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecs4.dll        ${ARCH_PREBUILT_DIRS_DEBUG}/libeay32.dll        ${ARCH_PREBUILT_DIRS_DEBUG}/qtcored4.dll        ${ARCH_PREBUILT_DIRS_DEBUG}/qtguid4.dll @@ -1460,6 +1482,10 @@ if (WINDOWS)        ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qmngd4.dll        ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qsvgd4.dll        ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qtiffd4.dll +      ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecsd4.dll +      ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecsd4.dll +      ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecsd4.dll +      ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecsd4.dll        SLPlugin        media_plugin_quicktime        media_plugin_webkit @@ -1493,7 +1519,7 @@ if (WINDOWS)      if(LLKDU_LIBRARY)        # kdu may not exist! -      add_dependencies(${VIEWER_BINARY_NAME} llkdu) +      add_dependencies(copy_w_viewer_manifest llkdu)      endif(LLKDU_LIBRARY)      if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 455c3587ff..ba78d80ad1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3585,7 +3585,7 @@        <key>Type</key>        <string>String</string>        <key>Value</key> -      <string>http://int.searchwww-phx0.damballah.lindenlab.com/viewer/[CATEGORY]?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]</string> +      <string>http://int.searchwww-phx0.damballah.lindenlab.com/viewer/[CATEGORY]?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]</string>      </map>      <key>HighResSnapshot</key>      <map> @@ -10378,6 +10378,17 @@        <key>Value</key>        <string>Default</string>      </map> +    <key>VoiceParticipantLeftRemoveDelay</key> +    <map> +      <key>Comment</key> +      <string>Timeout to remove participants who has left Voice chat from the list in Voice Controls Panel</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>10</integer> +    </map>      <key>VoicePort</key>      <map>        <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl index 28908a311d..0fad5b4b50 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl @@ -10,7 +10,6 @@  uniform sampler2DRect depthMap;  uniform sampler2DRect normalMap;  uniform sampler2DRect lightMap; -uniform sampler2DRect edgeMap;  uniform float dist_factor;  uniform float blur_size; @@ -46,53 +45,36 @@ void main()  	dlt /= max(-pos.z*dist_factor, 1.0); -	vec2 defined_weight = kern[0].xy; // special case the kern[0] (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' +	vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'  	vec4 col = defined_weight.xyxx * ccol; - -	float center_e = 1.0 - (texture2DRect(edgeMap, vary_fragcoord.xy).a+ -		      texture2DRect(edgeMap, vary_fragcoord.xy+dlt*0.333).a+ -	              texture2DRect(edgeMap, vary_fragcoord.xy-dlt*0.333).a); -	float e = center_e;  	for (int i = 1; i < 4; i++)  	{  		vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; -		 -		e = max(e, 0.0); -		 -		vec2 wght = kern[i].xy*e; -		 -		col += texture2DRect(lightMap, tc)*wght.xyxx; -		defined_weight += wght; -		 -		e *= e; -		e -= texture2DRect(edgeMap, tc.xy).a+ -			texture2DRect(edgeMap, tc.xy+dlt*0.333).a+ -			texture2DRect(edgeMap, tc.xy-dlt*0.333).a; +	        vec3 samppos = getPosition(tc).xyz;  +		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane +		if (d*d <= 0.003) +		{ +			col += texture2DRect(lightMap, tc)*kern[i].xyxx; +			defined_weight += kern[i].xy; +		}  	} - -	e = center_e;  	for (int i = 1; i < 4; i++)  	{  		vec2 tc = vary_fragcoord.xy - kern[i].z*dlt; -		 -		e = max(e, 0.0); -		 -		vec2 wght = kern[i].xy*e; -		 -		col += texture2DRect(lightMap, tc)*wght.xyxx; -		defined_weight += wght; -		 -		e *= e; -		e -= texture2DRect(edgeMap, tc.xy).a+ -			texture2DRect(edgeMap, tc.xy+dlt*0.333).a+ -			texture2DRect(edgeMap, tc.xy-dlt*0.333).a; +	        vec3 samppos = getPosition(tc).xyz;  +		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane +		if (d*d <= 0.003) +		{ +			col += texture2DRect(lightMap, tc)*kern[i].xyxx; +			defined_weight += kern[i].xy; +		}  	} +  	col /= defined_weight.xyxx;  	gl_FragColor = col; -	 -	//gl_FragColor = ccol;  } + diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index d20c23df80..4029bf95a0 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 20 +version 21  // NOTE: This is mostly identical to featuretable_mac.txt with a few differences  // Should be combined into one table @@ -28,6 +28,7 @@ RenderAvatarCloth			1	1  RenderAvatarLODFactor		1	1.0  RenderAvatarVP				1	1  RenderCubeMap				1	1 +RenderDelayVBUpdate			1	0  RenderFarClip				1	256  RenderFlexTimeFactor		1	1.0  RenderFogRatio				1	4.0 diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index 57d712ede7..61a8e51c50 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -1,4 +1,4 @@ -version 20 +version 21  // NOTE: This is mostly identical to featuretable_mac.txt with a few differences  // Should be combined into one table @@ -28,6 +28,7 @@ RenderAvatarCloth			1	1  RenderAvatarLODFactor		1	1.0  RenderAvatarVP				1	1  RenderCubeMap				1	1 +RenderDelayVBUpdate			1	0  RenderFarClip				1	256  RenderFlexTimeFactor		1	1.0  RenderFogRatio				1	4.0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 15974c0691..12d47a904c 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -1,4 +1,4 @@ -version 20 +version 21  // NOTE: This is mostly identical to featuretable_mac.txt with a few differences  // Should be combined into one table @@ -28,6 +28,7 @@ RenderAvatarCloth				0	0  RenderAvatarLODFactor			1	1.0  RenderAvatarVP					1	0  RenderCubeMap					1	1 +RenderDelayVBUpdate				1	0  RenderFarClip					1	256  RenderFlexTimeFactor			1	1.0  RenderFogRatio					1	4.0 diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt index 5c5c4e5b3c..cc8f6780e3 100644 --- a/indra/newview/gpu_table.txt +++ b/indra/newview/gpu_table.txt @@ -157,7 +157,7 @@ Intel Bear Lake					.*Intel.*Bear Lake.*				0		0  Intel Broadwater 				.*Intel.*Broadwater.*				0		0  Intel Brookdale					.*Intel.*Brookdale.*				0		0  Intel Cantiga					.*Intel.*Cantiga.*					0		0 -Intel Eaglelake					.*Intel.*Eaglelake.*				0		0 +Intel Eaglelake					.*Intel.*Eaglelake.*				0		1  Intel Montara					.*Intel.*Montara.*					0		0  Intel Springdale				.*Intel.*Springdale.*				0		0  Matrox							.*Matrox.*							0		0 diff --git a/indra/newview/linux_tools/register_secondlifeprotocol.sh b/indra/newview/linux_tools/register_secondlifeprotocol.sh index c7b4d55461..16e73cb854 100755 --- a/indra/newview/linux_tools/register_secondlifeprotocol.sh +++ b/indra/newview/linux_tools/register_secondlifeprotocol.sh @@ -22,13 +22,12 @@ else  fi  # Register handler for KDE-aware apps -if [ -z "$KDEHOME" ]; then -    KDEHOME=~/.kde -fi -LLKDEPROTDIR=${KDEHOME}/share/services -if [ -d "$LLKDEPROTDIR" ]; then -    LLKDEPROTFILE=${LLKDEPROTDIR}/secondlife.protocol -    cat > ${LLKDEPROTFILE} <<EOF || echo Warning: Did not register secondlife:// handler with KDE: Could not write ${LLKDEPROTFILE} +for LLKDECONFIG in kde-config kde4-config; do +    if [ `which $LLKDECONFIG` ]; then +        LLKDEPROTODIR=`$LLKDECONFIG --path services | cut -d ':' -f 1` +        if [ -d "$LLKDEPROTODIR" ]; then +            LLKDEPROTOFILE=${LLKDEPROTODIR}/secondlife.protocol +            cat > ${LLKDEPROTOFILE} <<EOF || echo Warning: Did not register secondlife:// handler with KDE: Could not write ${LLKDEPROTOFILE}   [Protocol]  exec=${HANDLER} '%u'  protocol=secondlife @@ -41,6 +40,9 @@ writing=false  makedir=false  deleting=false  EOF -else -    echo Warning: Did not register secondlife:// handler with KDE: Directory $LLKDEPROTDIR does not exist. -fi +        else +            echo Warning: Did not register secondlife:// handler with KDE: Directory $LLKDEPROTODIR does not exist. +        fi +    fi +done + diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 454e547155..79ba3fb51d 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -871,24 +871,31 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs  	if (mInitialWearablesUpdateReceived)  		return;  	mInitialWearablesUpdateReceived = true; +	 +	// If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account) +	// then auto-populate outfits from the library into the My Outfits folder. +	if (LLInventoryModel::getIsFirstTimeInViewer2()) +	{ +		gAgentWearables.populateMyOutfitsFolder(); +	}  	LLUUID agent_id;  	gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); -	const BOOL is_first_time_in_viewer2_0 = (gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) == LLUUID::null); - -  	LLVOAvatar* avatar = gAgent.getAvatarObject();  	if (avatar && (agent_id == avatar->getID()))  	{  		gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgentQueryManager.mUpdateSerialNum); +		const S32 NUM_BODY_PARTS = 4;  		S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData); -		if (num_wearables < 4) +		if (num_wearables < NUM_BODY_PARTS)  		{  			// Transitional state.  Avatars should always have at least their body parts (hair, eyes, shape and skin). -			// The fact that they don't have any here (only a dummy is sent) implies that this account existed -			// before we had wearables, or that the database has gotten messed up. +			// The fact that they don't have any here (only a dummy is sent) implies that either: +			// 1. This account existed before we had wearables +			// 2. The database has gotten messed up +			// 3. This is the account's first login (i.e. the wearables haven't been generated yet).  			return;  		} @@ -957,8 +964,6 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs  			gInventory.addObserver(outfit);  		} -		if (is_first_time_in_viewer2_0) -			gAgentWearables.populateMyOutfitsFolder();  	}  } diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index c5a1ffdcb3..2a8c55e5db 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -243,7 +243,6 @@ void LLAvatarActions::startAdhocCall(const std::vector<LLUUID>& ids)  		return;  	} -	// start the call once the session has fully initialized  	gIMMgr->autoStartCallOnStartup(session_id);  	make_ui_sound("UISndStartIM"); @@ -333,6 +332,54 @@ void LLAvatarActions::pay(const LLUUID& id)  	}  } +// static +void LLAvatarActions::kick(const LLUUID& id) +{ +	LLSD payload; +	payload["avatar_id"] = id; +	LLNotifications::instance().add("KickUser", LLSD(), payload, handleKick); +} + +// static +void LLAvatarActions::freeze(const LLUUID& id) +{ +	LLSD payload; +	payload["avatar_id"] = id; +	LLNotifications::instance().add("FreezeUser", LLSD(), payload, handleFreeze); +} + +// static +void LLAvatarActions::unfreeze(const LLUUID& id) +{ +	LLSD payload; +	payload["avatar_id"] = id; +	LLNotifications::instance().add("UnFreezeUser", LLSD(), payload, handleUnfreeze); +} + +//static  +void LLAvatarActions::csr(const LLUUID& id, std::string name) +{ +	if (name.empty()) return; +	 +	std::string url = "http://csr.lindenlab.com/agent/"; +	 +	// slow and stupid, but it's late +	S32 len = name.length(); +	for (S32 i = 0; i < len; i++) +	{ +		if (name[i] == ' ') +		{ +			url += "%20"; +		} +		else +		{ +			url += name[i]; +		} +	} +	 +	LLWeb::loadURL(url); +} +  //static   void LLAvatarActions::share(const LLUUID& id)  { @@ -457,6 +504,67 @@ bool LLAvatarActions::callbackAddFriendWithMessage(const LLSD& notification, con  }  // static +bool LLAvatarActions::handleKick(const LLSD& notification, const LLSD& response) +{ +	S32 option = LLNotification::getSelectedOption(notification, response); + +	if (option == 0) +	{ +		LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); +		LLMessageSystem* msg = gMessageSystem; + +		msg->newMessageFast(_PREHASH_GodKickUser); +		msg->nextBlockFast(_PREHASH_UserInfo); +		msg->addUUIDFast(_PREHASH_GodID,		gAgent.getID() ); +		msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID()); +		msg->addUUIDFast(_PREHASH_AgentID,   avatar_id ); +		msg->addU32("KickFlags", KICK_FLAGS_DEFAULT ); +		msg->addStringFast(_PREHASH_Reason,    response["message"].asString() ); +		gAgent.sendReliableMessage(); +	} +	return false; +} +bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& response) +{ +	S32 option = LLNotification::getSelectedOption(notification, response); + +	if (option == 0) +	{ +		LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); +		LLMessageSystem* msg = gMessageSystem; + +		msg->newMessageFast(_PREHASH_GodKickUser); +		msg->nextBlockFast(_PREHASH_UserInfo); +		msg->addUUIDFast(_PREHASH_GodID,		gAgent.getID() ); +		msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID()); +		msg->addUUIDFast(_PREHASH_AgentID,   avatar_id ); +		msg->addU32("KickFlags", KICK_FLAGS_FREEZE ); +		msg->addStringFast(_PREHASH_Reason, response["message"].asString() ); +		gAgent.sendReliableMessage(); +	} +	return false; +} +bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& response) +{ +	S32 option = LLNotification::getSelectedOption(notification, response); +	std::string text = response["message"].asString(); +	if (option == 0) +	{ +		LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); +		LLMessageSystem* msg = gMessageSystem; + +		msg->newMessageFast(_PREHASH_GodKickUser); +		msg->nextBlockFast(_PREHASH_UserInfo); +		msg->addUUIDFast(_PREHASH_GodID,		gAgent.getID() ); +		msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID()); +		msg->addUUIDFast(_PREHASH_AgentID,   avatar_id ); +		msg->addU32("KickFlags", KICK_FLAGS_UNFREEZE ); +		msg->addStringFast(_PREHASH_Reason,    text ); +		gAgent.sendReliableMessage(); +	} +	return false; +} +// static  bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& response)  {  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 01c18d4228..a4504ae679 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -138,11 +138,35 @@ public:  	 */	  	static void inviteToGroup(const LLUUID& id); +	/** +	 * Kick avatar off grid +	 */	 +	static void kick(const LLUUID& id); + +	/** +	 * Freeze avatar +	 */	 +	static void freeze(const LLUUID& id); + +	/** +	 * Unfreeze avatar +	 */	 +	static void unfreeze(const LLUUID& id); + +	/** +	 * Open csr page for avatar +	 */	 +	static void csr(const LLUUID& id, std::string name); + +	  private:  	static bool callbackAddFriend(const LLSD& notification, const LLSD& response);  	static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);  	static bool handleRemove(const LLSD& notification, const LLSD& response);  	static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id); +	static bool handleKick(const LLSD& notification, const LLSD& response); +	static bool handleFreeze(const LLSD& notification, const LLSD& response); +	static bool handleUnfreeze(const LLSD& notification, const LLSD& response);  	static void callback_invite_to_group(LLUUID group_id, LLUUID id);  	// Just request friendship, no dialog. diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 71b23e1383..b3ef6464f6 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -33,7 +33,7 @@  #include "llviewerprecompiledheaders.h"  #include "llavatarlist.h" -#include "llagent.h" // for comparator +#include "llagentdata.h" // for comparator  // newview  #include "llcallingcard.h" // for LLAvatarTracker @@ -51,6 +51,12 @@ static const F32 LIT_UPDATE_PERIOD = 5;  // Used to limit time spent for avatar list update per frame.  static const unsigned ADD_LIMIT = 50; +bool LLAvatarList::contains(const LLUUID& id) +{ +	const uuid_vector_t& ids = getIDs(); +	return std::find(ids.begin(), ids.end(), id) != ids.end(); +} +  void LLAvatarList::toggleIcons()  {  	// Save the new value for new items to use. @@ -322,7 +328,6 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is  	item->setAvatarId(id, mIgnoreOnlineStatus);  	item->setOnline(mIgnoreOnlineStatus ? true : is_online);  	item->showLastInteractionTime(mShowLastInteractionTime); -	item->setContextMenu(mContextMenu);  	item->childSetVisible("info_btn", false);  	item->setAvatarIconVisible(mShowIcons); @@ -425,11 +430,11 @@ bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_  {  	//keep agent on top, if first is agent,   	//then we need to return true to elevate this id, otherwise false. -	if(avatar_item1->getAvatarId() == gAgent.getID()) +	if(avatar_item1->getAvatarId() == gAgentID)  	{  		return true;  	} -	else if (avatar_item2->getAvatarId() == gAgent.getID()) +	else if (avatar_item2->getAvatarId() == gAgentID)  	{  		return false;  	} diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index e913be0f62..0d2ce884ae 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -75,6 +75,7 @@ public:  	void setNameFilter(const std::string& filter);  	void setDirty(bool val = true)						{ mDirty = val; }  	uuid_vector_t& getIDs() 							{ return mIDs; } +	bool contains(const LLUUID& id);  	void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; } diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 072eebdf2d..8bc11b0c1c 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -43,6 +43,12 @@  #include "lltextutil.h"  #include "llbutton.h" +bool LLAvatarListItem::sStaticInitialized = false; +S32 LLAvatarListItem::sIconWidth = 0; +S32 LLAvatarListItem::sInfoBtnWidth = 0; +S32 LLAvatarListItem::sProfileBtnWidth = 0; +S32 LLAvatarListItem::sSpeakingIndicatorWidth = 0; +  LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/)  :	LLPanel(),  	mAvatarIcon(NULL), @@ -51,7 +57,6 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/)  	mSpeakingIndicator(NULL),  	mInfoBtn(NULL),  	mProfileBtn(NULL), -	mContextMenu(NULL),  	mOnlineStatus(E_UNKNOWN),  	mShowInfoBtn(true),  	mShowProfileBtn(true) @@ -88,10 +93,15 @@ BOOL  LLAvatarListItem::postBuild()  	// Remember avatar icon width including its padding from the name text box,  	// so that we can hide and show the icon again later. -	mIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft; -	mInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight; -	mProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight; -	mSpeakingIndicatorWidth = mSpeakingIndicator->getRect().mRight - mAvatarName->getRect().mRight;  +	if (!sStaticInitialized) +	{ +		sIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft; +		sInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight; +		sProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight; +		sSpeakingIndicatorWidth = mSpeakingIndicator->getRect().mRight - mAvatarName->getRect().mRight; + +		sStaticInitialized = true; +	}  /*  	if(!p.buttons.profile) @@ -148,7 +158,6 @@ void LLAvatarListItem::changed(U32 mask)  void LLAvatarListItem::setOnline(bool online)  {  	// *FIX: setName() overrides font style set by setOnline(). Not an issue ATM. -	// *TODO: Make the colors configurable via XUI.  	if (mOnlineStatus != E_UNKNOWN && (bool) mOnlineStatus == online)  		return; @@ -156,11 +165,7 @@ void LLAvatarListItem::setOnline(bool online)  	mOnlineStatus = (EOnlineStatus) online;  	// Change avatar name font style depending on the new online status. -	mAvatarNameStyle.color = online ? LLColor4::white : LLColor4::grey; -	setNameInternal(mAvatarName->getText(), mHighlihtSubstring); - -	// Make the icon fade if the avatar goes offline. -	mAvatarIcon->setColor(online ? LLColor4::white : LLColor4::smoke); +	setStyle(online ? IS_ONLINE : IS_OFFLINE);  }  void LLAvatarListItem::setName(const std::string& name) @@ -173,6 +178,21 @@ void LLAvatarListItem::setHighlight(const std::string& highlight)  	setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);  } +void LLAvatarListItem::setStyle(EItemStyle item_style) +{ +	item_style_map_t& item_styles_params_map = getItemStylesParams(); + +	mAvatarNameStyle = item_styles_params_map[item_style]; + +	// *NOTE: You cannot set the style on a text box anymore, you must +	// rebuild the text.  This will cause problems if the text contains +	// hyperlinks, as their styles will be wrong. +	setNameInternal(mAvatarName->getText(), mHighlihtSubstring); + +	icon_color_map_t& item_icon_color_map = getItemIconColorMap(); +	mAvatarIcon->setColor(item_icon_color_map[item_style]); +} +  void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)  {  	if (mAvatarId.notNull()) @@ -214,7 +234,7 @@ void LLAvatarListItem::setShowInfoBtn(bool show)  	if(mShowInfoBtn == show)  		return;  	mShowInfoBtn = show; -	S32 width_delta = show ? - mInfoBtnWidth : mInfoBtnWidth; +	S32 width_delta = show ? - sInfoBtnWidth : sInfoBtnWidth;  	//Translating speaking indicator  	mSpeakingIndicator->translate(width_delta, 0); @@ -228,7 +248,7 @@ void LLAvatarListItem::setShowProfileBtn(bool show)  	if(mShowProfileBtn == show)  			return;  	mShowProfileBtn = show; -	S32 width_delta = show ? - mProfileBtnWidth : mProfileBtnWidth; +	S32 width_delta = show ? - sProfileBtnWidth : sProfileBtnWidth;  	//Translating speaking indicator  	mSpeakingIndicator->translate(width_delta, 0); @@ -242,7 +262,7 @@ void LLAvatarListItem::setSpeakingIndicatorVisible(bool visible)  	if (mSpeakingIndicator->getVisible() == (BOOL)visible)  		return;  	mSpeakingIndicator->setVisible(visible); -	S32 width_delta = visible ? - mSpeakingIndicatorWidth : mSpeakingIndicatorWidth; +	S32 width_delta = visible ? - sSpeakingIndicatorWidth : sSpeakingIndicatorWidth;  	//Reshaping avatar name  	mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight()); @@ -259,7 +279,7 @@ void LLAvatarListItem::setAvatarIconVisible(bool visible)  	// Move the avatar name horizontally by icon size + its distance from the avatar name.  	LLRect name_rect = mAvatarName->getRect(); -	name_rect.mLeft += visible ? mIconWidth : -mIconWidth; +	name_rect.mLeft += visible ? sIconWidth : -sIconWidth;  	mAvatarName->setRect(name_rect);  } @@ -327,10 +347,10 @@ void LLAvatarListItem::onNameCache(const std::string& first_name, const std::str  void LLAvatarListItem::reshapeAvatarName()  {  	S32 width_delta = 0; -	width_delta += mShowProfileBtn ? mProfileBtnWidth : 0; -	width_delta += mSpeakingIndicator->getVisible() ? mSpeakingIndicatorWidth : 0; -	width_delta += mAvatarIcon->getVisible() ? mIconWidth : 0; -	width_delta += mShowInfoBtn ? mInfoBtnWidth : 0; +	width_delta += mShowProfileBtn ? sProfileBtnWidth : 0; +	width_delta += mSpeakingIndicator->getVisible() ? sSpeakingIndicatorWidth : 0; +	width_delta += mAvatarIcon->getVisible() ? sIconWidth : 0; +	width_delta += mShowInfoBtn ? sInfoBtnWidth : 0;  	width_delta += mLastInteractionTime->getVisible() ? mLastInteractionTime->getRect().getWidth() : 0;  	S32 height = mAvatarName->getRect().getHeight(); @@ -386,3 +406,90 @@ std::string LLAvatarListItem::formatSeconds(U32 secs)  	args["[COUNT]"] = llformat("%u", count);  	return getString(fmt, args);  } + +// static +LLAvatarListItem::item_style_map_t& LLAvatarListItem::getItemStylesParams() +{ +	static item_style_map_t item_styles_params_map; +	if (!item_styles_params_map.empty()) return item_styles_params_map; + +	LLPanel::Params params = LLUICtrlFactory::getDefaultParams<LLPanel>(); +	LLPanel* params_panel = LLUICtrlFactory::create<LLPanel>(params); + +	BOOL sucsess = LLUICtrlFactory::instance().buildPanel(params_panel, "panel_avatar_list_item_params.xml"); + +	if (sucsess) +	{ + +		item_styles_params_map.insert( +			std::make_pair(IS_DEFAULT, +			params_panel->getChild<LLTextBox>("default_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_VOICE_INVITED, +			params_panel->getChild<LLTextBox>("voice_call_invited_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_VOICE_JOINED, +			params_panel->getChild<LLTextBox>("voice_call_joined_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_VOICE_LEFT, +			params_panel->getChild<LLTextBox>("voice_call_left_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_ONLINE, +			params_panel->getChild<LLTextBox>("online_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_OFFLINE, +			params_panel->getChild<LLTextBox>("offline_style")->getDefaultStyle())); +	} +	else +	{ +		item_styles_params_map.insert(std::make_pair(IS_DEFAULT, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_VOICE_INVITED, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_VOICE_JOINED, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_VOICE_LEFT, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_ONLINE, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_OFFLINE, LLStyle::Params())); +	} +	if (params_panel) params_panel->die(); + +	return item_styles_params_map; +} + +// static +LLAvatarListItem::icon_color_map_t& LLAvatarListItem::getItemIconColorMap() +{ +	static icon_color_map_t item_icon_color_map; +	if (!item_icon_color_map.empty()) return item_icon_color_map; + +	item_icon_color_map.insert( +		std::make_pair(IS_DEFAULT, +		LLUIColorTable::instance().getColor("AvatarListItemIconDefaultColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_VOICE_INVITED, +		LLUIColorTable::instance().getColor("AvatarListItemIconVoiceInvitedColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_VOICE_JOINED, +		LLUIColorTable::instance().getColor("AvatarListItemIconVoiceJoinedColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_VOICE_LEFT, +		LLUIColorTable::instance().getColor("AvatarListItemIconVoiceLeftColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_ONLINE, +		LLUIColorTable::instance().getColor("AvatarListItemIconOnlineColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_OFFLINE, +		LLUIColorTable::instance().getColor("AvatarListItemIconOfflineColor", LLColor4::white))); + +	return item_icon_color_map; +} + +// EOF diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index aa1b7593f5..79303b55cc 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -46,6 +46,15 @@ class LLAvatarIconCtrl;  class LLAvatarListItem : public LLPanel, public LLFriendObserver  {  public: +	typedef enum e_item_style_type { +		IS_DEFAULT, +		IS_VOICE_INVITED, +		IS_VOICE_JOINED, +		IS_VOICE_LEFT, +		IS_ONLINE, +		IS_OFFLINE, +	} EItemStyle; +  	class ContextMenu  	{  	public: @@ -73,6 +82,7 @@ public:  	void setOnline(bool online);  	void setName(const std::string& name);  	void setHighlight(const std::string& highlight); +	void setStyle(EItemStyle item_style);  	void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);  	void setLastInteractionTime(U32 secs_since);  	//Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly @@ -91,8 +101,6 @@ public:  	void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); }  	void showLastInteractionTime(bool show); -	void setContextMenu(ContextMenu* menu) { mContextMenu = menu; } -  	/**  	 * This method was added to fix EXT-2364 (Items in group/ad-hoc IM participant list (avatar names) should be reshaped when adding/removing the "(Moderator)" label)  	 * But this is a *HACK. The real reason of it was in incorrect logic while hiding profile/info/speaker buttons @@ -106,6 +114,8 @@ protected:  	 */  	LLOutputMonitorCtrl* mSpeakingIndicator; +	LLAvatarIconCtrl* mAvatarIcon; +  private:  	typedef enum e_online_status { @@ -119,14 +129,18 @@ private:  	std::string formatSeconds(U32 secs); -	LLAvatarIconCtrl* mAvatarIcon; +	typedef std::map<EItemStyle, LLStyle::Params> item_style_map_t; +	static item_style_map_t& getItemStylesParams(); + +	typedef std::map<EItemStyle, LLColor4> icon_color_map_t; +	static icon_color_map_t& getItemIconColorMap(); +  	LLTextBox* mAvatarName;  	LLTextBox* mLastInteractionTime;  	LLStyle::Params mAvatarNameStyle;  	LLButton* mInfoBtn;  	LLButton* mProfileBtn; -	ContextMenu* mContextMenu;  	LLUUID mAvatarId;  	std::string mHighlihtSubstring; // substring to highlight @@ -135,10 +149,12 @@ private:  	//Speaker indicator and avatar name coords are translated accordingly  	bool mShowInfoBtn;  	bool mShowProfileBtn; -	S32	 mIconWidth; // icon width + padding -	S32  mInfoBtnWidth; //info btn width + padding -	S32  mProfileBtnWidth; //profile btn width + padding -	S32  mSpeakingIndicatorWidth; //speaking indicator width + padding + +	static bool	sStaticInitialized; // this variable is introduced to improve code readability +	static S32	sIconWidth; // icon width + padding +	static S32  sInfoBtnWidth; //info btn width + padding +	static S32  sProfileBtnWidth; //profile btn width + padding +	static S32  sSpeakingIndicatorWidth; //speaking indicator width + padding  };  #endif //LL_LLAVATARLISTITEM_H diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index ab657e0e99..976b312509 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -81,9 +81,6 @@ LLBottomTray::LLBottomTray(const LLSD&)  	LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraPresets, _2)); -	//managing chiclets for voice calls -	LLIMModel::getInstance()->addNewMsgCallback(boost::bind(&LLBottomTray::onNewIM, this, _1)); -  	//this is to fix a crash that occurs because LLBottomTray is a singleton  	//and thus is deleted at the end of the viewers lifetime, but to be cleanly  	//destroyed LLBottomTray requires some subsystems that are long gone @@ -151,10 +148,13 @@ void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& nam  {  	if (!getChicletPanel()) return; -	if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return; +	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); +	if (!session) return; -	// For im sessions started as voice call chiclet gets created on the first incoming message -	if (gIMMgr->isVoiceCall(session_id)) return; +	// no need to spawn chiclets for participants in P2P calls called through Avaline +	if (session->isP2P() && session->isOtherParticipantAvaline()) return; + +	if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;  	LLIMChiclet* chiclet = createIMChiclet(session_id);  	if(chiclet) @@ -197,27 +197,6 @@ void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID&  	}  } -void LLBottomTray::onNewIM(const LLSD& data) -{ -	LLUUID from_id = data["from_id"]; -	if (from_id.isNull() || gAgentID == from_id) return; - -	LLUUID session_id = data["session_id"]; -	if (session_id.isNull()) return; - -	if (!gIMMgr->isVoiceCall(session_id)) return; - -	if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return; - -	//first real message, time to create chiclet -	LLIMChiclet* chiclet = createIMChiclet(session_id); -	if(chiclet) -	{ -		chiclet->setIMSessionName(LLIMModel::getInstance()->getName(session_id)); -		chiclet->setOtherParticipantId(LLIMModel::getInstance()->getOtherParticipantID(session_id)); -	} -} -  S32 LLBottomTray::getTotalUnreadIMCount()  {  	return getChicletPanel()->getTotalUnreadIMCount(); diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 5cd3f15746..9be0e5810f 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -75,8 +75,6 @@ public:  	virtual void sessionRemoved(const LLUUID& session_id);  	void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); -	void onNewIM(const LLSD& data); -  	S32 getTotalUnreadIMCount();  	virtual void reshape(S32 width, S32 height, BOOL called_from_parent); diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 20739d2401..1b4c274bfb 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -40,6 +40,7 @@  #include "llagent.h"  #include "llagentdata.h" // for gAgentID +#include "llavatariconctrl.h"  #include "llavatarlist.h"  #include "llbottomtray.h"  #include "llimfloater.h" @@ -48,6 +49,7 @@  #include "llspeakers.h"  #include "lltransientfloatermgr.h" +static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids);  class LLNonAvatarCaller : public LLAvatarListItem  { @@ -66,6 +68,8 @@ public:  			showLastInteractionTime(false);  			setShowProfileBtn(false);  			setShowInfoBtn(false); +			mAvatarIcon->setValue("Avaline_Icon"); +			mAvatarIcon->setToolTip(std::string(""));  		}  		return rv;  	} @@ -79,17 +83,38 @@ static void* create_non_avatar_caller(void*)  	return new LLNonAvatarCaller;  } +LLCallFloater::LLAvatarListItemRemoveTimer::LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id) +: LLEventTimer(period) +, mRemoveCallback(remove_cb) +, mSpeakerId(speaker_id) +{ +} + +BOOL LLCallFloater::LLAvatarListItemRemoveTimer::tick() +{ +	if (mRemoveCallback) +	{ +		mRemoveCallback(mSpeakerId); +	} +	return TRUE; +} +  LLCallFloater::LLCallFloater(const LLSD& key)  : LLDockableFloater(NULL, false, key)  , mSpeakerManager(NULL) -, mPaticipants(NULL) +, mParticipants(NULL)  , mAvatarList(NULL)  , mNonAvatarCaller(NULL)  , mVoiceType(VC_LOCAL_CHAT)  , mAgentPanel(NULL)  , mSpeakingIndicator(NULL)  , mIsModeratorMutedVoice(false) +, mInitParticipantsVoiceState(false) +, mVoiceLeftRemoveDelay(10)  { +	static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10); +	mVoiceLeftRemoveDelay = voice_left_remove_delay; +  	mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);  	LLVoiceClient::getInstance()->addObserver(this);  	LLTransientFloaterMgr::getInstance()->addControlView(this); @@ -97,8 +122,12 @@ LLCallFloater::LLCallFloater(const LLSD& key)  LLCallFloater::~LLCallFloater()  { -	delete mPaticipants; -	mPaticipants = NULL; +	resetVoiceRemoveTimers(); + +	delete mParticipants; +	mParticipants = NULL; + +	mAvatarListRefreshConnection.disconnect();  	// Don't use LLVoiceClient::getInstance() here   	// singleton MAY have already been destroyed. @@ -114,6 +143,8 @@ BOOL LLCallFloater::postBuild()  {  	LLDockableFloater::postBuild();  	mAvatarList = getChild<LLAvatarList>("speakers_list"); +	mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLCallFloater::onAvatarListRefreshed, this)); +  	childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this));  	mNonAvatarCaller = getChild<LLNonAvatarCaller>("non_avatar_caller"); @@ -144,7 +175,11 @@ void LLCallFloater::draw()  	// It should be done only when she joins or leaves voice chat.  	// But seems that LLVoiceClientParticipantObserver is not enough to satisfy this requirement.  	// *TODO: mantipov: remove from draw() -	onChange(); + +	// NOTE: it looks like calling onChange() here is not necessary, +	// but sometime it is not called properly from the observable object. +	// Seems this is a problem somewhere in Voice Client (LLVoiceClient::participantAddedEvent) +//	onChange();  	bool is_moderator_muted = gVoiceClient->getIsModeratorMuted(gAgentID); @@ -153,15 +188,27 @@ void LLCallFloater::draw()  		setModeratorMutedVoice(is_moderator_muted);  	} +	// Need to resort the participant list if it's in sort by recent speaker order. +	if (mParticipants) +		mParticipants->updateRecentSpeakersOrder(); +  	LLDockableFloater::draw();  }  // virtual  void LLCallFloater::onChange()  { -	if (NULL == mPaticipants) return; +	if (NULL == mParticipants) return; -	mPaticipants->refreshVoiceState(); +	updateParticipantsVoiceState(); + +	// Add newly joined participants. +	std::vector<LLUUID> speakers_uuids; +	get_voice_participants_uuids(speakers_uuids); +	for (std::vector<LLUUID>::const_iterator it = speakers_uuids.begin(); it != speakers_uuids.end(); it++) +	{ +		mParticipants->addAvatarIDExceptAgent(*it); +	}  } @@ -242,8 +289,8 @@ void LLCallFloater::updateSession()  	bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;  	childSetVisible("leave_call_btn", !is_local_chat); -	refreshPartisipantList(); -	updateModeratorState(); +	refreshParticipantList(); +	updateAgentModeratorState();  	//show floater for voice calls  	if (!is_local_chat) @@ -257,10 +304,17 @@ void LLCallFloater::updateSession()  	}  } -void LLCallFloater::refreshPartisipantList() +void LLCallFloater::refreshParticipantList()  { -	delete mPaticipants; -	mPaticipants = NULL; +	// lets forget states from the previous session +	// for timers... +	resetVoiceRemoveTimers(); + +	// ...and for speaker state +	mSpeakerStateMap.clear(); + +	delete mParticipants; +	mParticipants = NULL;  	mAvatarList->clear();  	bool non_avatar_caller = false; @@ -280,13 +334,30 @@ void LLCallFloater::refreshPartisipantList()  	if (!non_avatar_caller)  	{ -		mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList); +		mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT); +		mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));  		if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)  		{  			mAvatarList->setNoItemsCommentText(getString("no_one_near"));  		} -		mPaticipants->refreshVoiceState();	 + +		// we have to made delayed initialization of voice state of participant list. +		// it will be performed after first LLAvatarList refreshing in the onAvatarListRefreshed(). +		mInitParticipantsVoiceState = true; +	} +} + +void LLCallFloater::onAvatarListRefreshed() +{ +	if (mInitParticipantsVoiceState) +	{ +		initParticipantsVoiceState(); +		mInitParticipantsVoiceState = false; +	} +	else +	{ +		updateParticipantsVoiceState();  	}  } @@ -366,7 +437,7 @@ void LLCallFloater::setModeratorMutedVoice(bool moderator_muted)  	mSpeakingIndicator->setIsMuted(moderator_muted);  } -void LLCallFloater::updateModeratorState() +void LLCallFloater::updateAgentModeratorState()  {  	std::string name;  	gCacheName->getFullName(gAgentID, name); @@ -388,4 +459,266 @@ void LLCallFloater::updateModeratorState()  	}  	mAgentPanel->childSetValue("user_text", name);  } + +static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids) +{ +	// Get a list of participants from VoiceClient +	LLVoiceClient::participantMap *voice_map = gVoiceClient->getParticipantList(); +	if (voice_map) +	{ +		for (LLVoiceClient::participantMap::const_iterator iter = voice_map->begin(); +			iter != voice_map->end(); ++iter) +		{ +			LLUUID id = (*iter).second->mAvatarID; +			speakers_uuids.push_back(id); +		} +	} +} + +void LLCallFloater::initParticipantsVoiceState() +{ +	// Set initial status for each participant in the list. +	std::vector<LLPanel*> items; +	mAvatarList->getItems(items); +	std::vector<LLPanel*>::const_iterator +		it = items.begin(), +		it_end = items.end(); + + +	std::vector<LLUUID> speakers_uuids; +	get_voice_participants_uuids(speakers_uuids); + +	for(; it != it_end; ++it) +	{ +		LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it); +		 +		if (!item)	continue; +		 +		LLUUID speaker_id = item->getAvatarId(); + +		std::vector<LLUUID>::const_iterator speaker_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), speaker_id); + +		// If an avatarID assigned to a panel is found in a speakers list +		// obtained from VoiceClient we assign the JOINED status to the owner +		// of this avatarID. +		if (speaker_iter != speakers_uuids.end()) +		{ +			setState(item, STATE_JOINED); +		} +		else +		{ +			LLPointer<LLSpeaker> speakerp = mSpeakerManager->findSpeaker(speaker_id); +			// If someone has already left the call before, we create his +			// avatar row panel with HAS_LEFT status and remove it after +			// the timeout, otherwise we create a panel with INVITED status +			if (speakerp.notNull() && speakerp.get()->mHasLeftCurrentCall) +			{ +				setState(item, STATE_LEFT); +			} +			else +			{ +				setState(item, STATE_INVITED); +			} +		} +	} +} + +void LLCallFloater::updateParticipantsVoiceState() +{ +	std::vector<LLUUID> speakers_list; + +	// Get a list of participants from VoiceClient +	std::vector<LLUUID> speakers_uuids; +	get_voice_participants_uuids(speakers_uuids); + +	// Updating the status for each participant already in list. +	std::vector<LLPanel*> items; +	mAvatarList->getItems(items); +	std::vector<LLPanel*>::const_iterator +		it = items.begin(), +		it_end = items.end(); + +	for(; it != it_end; ++it) +	{ +		LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it); +		if (!item) continue; + +		const LLUUID participant_id = item->getAvatarId(); +		bool found = false; + +		std::vector<LLUUID>::iterator speakers_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), participant_id); + +		lldebugs << "processing speaker: " << item->getAvatarName() << ", " << item->getAvatarId() << llendl; + +		// If an avatarID assigned to a panel is found in a speakers list +		// obtained from VoiceClient we assign the JOINED status to the owner +		// of this avatarID. +		if (speakers_iter != speakers_uuids.end()) +		{ +			setState(item, STATE_JOINED); + +			LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id); +			if (speaker.isNull()) +				continue; +			speaker->mHasLeftCurrentCall = FALSE; + +			speakers_uuids.erase(speakers_iter); +			found = true; +		} + +		if (!found) +		{ +			// If an avatarID is not found in a speakers list from VoiceClient and +			// a panel with this ID has a JOINED status this means that this person +			// HAS LEFT the call. +			if ((getState(participant_id) == STATE_JOINED)) +			{ +				if (mVoiceType == VC_LOCAL_CHAT) +				{ +					// Don't display avatars that aren't in our nearby chat range anymore as "left". Remove them immediately. +					removeVoiceLeftParticipant(participant_id); +				} +				else +				{ +					setState(item, STATE_LEFT); + +					LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId()); +					if (speaker.isNull()) +					{ +						continue; +					} + +					speaker->mHasLeftCurrentCall = TRUE; +				} +			} +			// If an avatarID is not found in a speakers list from VoiceClient and +			// a panel with this ID has a LEFT status this means that this person +			// HAS ENTERED session but it is not in voice chat yet. So, set INVITED status +			else if ((getState(participant_id) != STATE_LEFT)) +			{ +				setState(item, STATE_INVITED); +			} +			else +			{ +				llwarns << "Unsupported (" << getState(participant_id) << ") state: " << item->getAvatarName()  << llendl; +			} +		} +	} +} + +void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state) +{ +	// *HACK: mantipov: sometimes such situation is possible while switching to voice channel: +/* +	- voice channel is switched to the one user is joining +	- participant list is initialized with voice states: agent is in voice +	- than such log messages were found (with agent UUID) +			- LLVivoxProtocolParser::process_impl: parsing: <Response requestId="22" action="Session.MediaDisconnect.1"><ReturnCode>0</ReturnCode><Results><StatusCode>0</StatusCode><StatusString /></Results><InputXml><Request requestId="22" action="Session.MediaDisconnect.1"><SessionGroupHandle>9</SessionGroupHandle><SessionHandle>12</SessionHandle><Media>Audio</Media></Request></InputXml></Response> +			- LLVoiceClient::sessionState::removeParticipant: participant "sip:x2pwNkMbpR_mK4rtB_awASA==@bhr.vivox.com" (da9c0d90-c6e9-47f9-8ae2-bb41fdac0048) removed. +	- and than while updating participants voice states agent is marked as HAS LEFT +	- next updating of LLVoiceClient state makes agent JOINED +	So, lets skip HAS LEFT state for agent's avatar +*/ +	if (STATE_LEFT == state && item->getAvatarId() == gAgentID) return; + +	setState(item->getAvatarId(), state); + +	switch (state) +	{ +	case STATE_INVITED: +		item->setStyle(LLAvatarListItem::IS_VOICE_INVITED); +		break; +	case STATE_JOINED: +		removeVoiceRemoveTimer(item->getAvatarId()); +		item->setStyle(LLAvatarListItem::IS_VOICE_JOINED); +		break; +	case STATE_LEFT: +		{ +			setVoiceRemoveTimer(item->getAvatarId()); +			item->setStyle(LLAvatarListItem::IS_VOICE_LEFT); +		} +		break; +	default: +		llwarns << "Unrecognized avatar panel state (" << state << ")" << llendl; +		break; +	} +} + +void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id) +{ + +	// If there is already a started timer for the current panel don't do anything. +	bool no_timer_for_current_panel = true; +	if (mVoiceLeftTimersMap.size() > 0) +	{ +		timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id); +		if (found_it != mVoiceLeftTimersMap.end()) +		{ +			no_timer_for_current_panel = false; +		} +	} + +	if (no_timer_for_current_panel) +	{ +		// Starting a timer to remove an avatar row panel after timeout +		mVoiceLeftTimersMap.insert(timer_pair(voice_speaker_id, +			new LLAvatarListItemRemoveTimer(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), mVoiceLeftRemoveDelay, voice_speaker_id))); +	} +} + +void LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id) +{ +	if (mVoiceLeftTimersMap.size() > 0) +	{ +		mVoiceLeftTimersMap.erase(mVoiceLeftTimersMap.find(voice_speaker_id)); +	} + +	LLAvatarList::uuid_vector_t& speaker_uuids = mAvatarList->getIDs(); +	LLAvatarList::uuid_vector_t::iterator pos = std::find(speaker_uuids.begin(), speaker_uuids.end(), voice_speaker_id); +	if(pos != speaker_uuids.end()) +	{ +		speaker_uuids.erase(pos); +		mAvatarList->setDirty(); +	} +} + + +void LLCallFloater::resetVoiceRemoveTimers() +{ +	if (mVoiceLeftTimersMap.size() > 0) +	{ +		for (timers_map::iterator iter = mVoiceLeftTimersMap.begin(); +			iter != mVoiceLeftTimersMap.end(); ++iter) +		{ +			delete iter->second; +		} +	} +	mVoiceLeftTimersMap.clear(); +} + +void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id) +{ +	// Remove the timer if it has been already started +	if (mVoiceLeftTimersMap.size() > 0) +	{ +		timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id); +		if (found_it != mVoiceLeftTimersMap.end()) +		{ +			delete found_it->second; +			mVoiceLeftTimersMap.erase(found_it); +		} +	} +} + +bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id) +{ +	if (mVoiceType != VC_LOCAL_CHAT) +		return true; + +	// A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice). +	std::vector<LLUUID> speakers; +	get_voice_participants_uuids(speakers); +	return std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end(); +} +  //EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index f9c9149085..3df9e333c5 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -38,6 +38,7 @@  #include "llvoiceclient.h"  class LLAvatarList; +class LLAvatarListItem;  class LLNonAvatarCaller;  class LLOutputMonitorCtrl;  class LLParticipantList; @@ -56,6 +57,9 @@ class LLSpeakerMgr;  class LLCallFloater : public LLDockableFloater, LLVoiceClientParticipantObserver  {  public: + +	LOG_CLASS(LLCallFloater); +  	LLCallFloater(const LLSD& key);  	~LLCallFloater(); @@ -81,6 +85,16 @@ private:  		VC_PEER_TO_PEER  	}EVoiceControls; +	typedef enum e_speaker_state +	{ +		STATE_UNKNOWN, +		STATE_INVITED, +		STATE_JOINED, +		STATE_LEFT, +	} ESpeakerState; + +	typedef std::map<LLUUID, ESpeakerState> speaker_state_map_t; +  	void leaveCall();  	/** @@ -94,24 +108,140 @@ private:  	/**  	 * Refreshes participant list according to current Voice Channel  	 */ -	void refreshPartisipantList(); +	void refreshParticipantList(); +	/** +	 * Handles event on avatar list is refreshed after it was marked dirty. +	 * +	 * It sets initial participants voice states (once after the first refreshing) +	 * and updates voice states each time anybody is joined/left voice chat in session. +	 */ +	void onAvatarListRefreshed();  	void updateTitle();  	void initAgentData();  	void setModeratorMutedVoice(bool moderator_muted); -	void updateModeratorState(); +	void updateAgentModeratorState(); + +	/** +	 * Sets initial participants voice states in avatar list (Invited, Joined, Has Left). +	 * +	 * @see refreshParticipantList() +	 * @see onAvatarListRefreshed() +	 * @see mInitParticipantsVoiceState +	 */ +	void initParticipantsVoiceState(); + +	/** +	 * Updates participants voice states in avatar list (Invited, Joined, Has Left). +	 * +	 * @see onAvatarListRefreshed() +	 * @see onChanged() +	 */ +	void updateParticipantsVoiceState(); + +	void setState(LLAvatarListItem* item, ESpeakerState state); +	void setState(const LLUUID& speaker_id, ESpeakerState state) +	{ +		lldebugs << "Storing state: " << speaker_id << ", " << state << llendl; +		mSpeakerStateMap[speaker_id] = state; +	} + +	ESpeakerState getState(const LLUUID& speaker_id) +	{ +		lldebugs << "Getting state: " << speaker_id << ", " << mSpeakerStateMap[speaker_id] << llendl; + +		return mSpeakerStateMap[speaker_id]; +	} + +	/** +	 * Instantiates new LLAvatarListItemRemoveTimer and adds it into the map if it is not already created. +	 * +	 * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list when timer expires. +	 */ +	void setVoiceRemoveTimer(const LLUUID& voice_speaker_id); + +	/** +	 * Removes specified by UUID Avatar List item. +	 * +	 * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list. +	 */ +	void removeVoiceLeftParticipant(const LLUUID& voice_speaker_id); + +	/** +	 * Deletes all timers from the list to prevent started timers from ticking after destruction +	 * and after switching on another voice channel. +	 */ +	void resetVoiceRemoveTimers(); + +	/** +	 * Removes specified by UUID timer from the map. +	 * +	 * @param voice_speaker_id LLUUID of Avatar List item whose timer should be removed from the map. +	 */ +	void removeVoiceRemoveTimer(const LLUUID& voice_speaker_id); + +	/** +	 * Called by LLParticipantList before adding a speaker to the participant list. +	 * +	 * If false is returned, the speaker will not be added to the list. +	 * +	 * @param speaker_id Speaker to validate. +	 * @return true if this is a valid speaker, false otherwise. +	 */ +	bool validateSpeaker(const LLUUID& speaker_id);  private: +	speaker_state_map_t mSpeakerStateMap;  	LLSpeakerMgr* mSpeakerManager; -	LLParticipantList* mPaticipants; +	LLParticipantList* mParticipants;  	LLAvatarList* mAvatarList;  	LLNonAvatarCaller* mNonAvatarCaller;  	EVoiceControls mVoiceType;  	LLPanel* mAgentPanel;  	LLOutputMonitorCtrl* mSpeakingIndicator;  	bool mIsModeratorMutedVoice; + +	/** +	 * Flag indicated that participants voice states should be initialized. +	 * +	 * It is used due to Avatar List has delayed refreshing after it content is changed. +	 * Real initializing is performed when Avatar List is first time refreshed. +	 * +	 * @see onAvatarListRefreshed() +	 * @see initParticipantsVoiceState() +	 */ +	bool mInitParticipantsVoiceState; + +	boost::signals2::connection mAvatarListRefreshConnection; + +	/** +	 * class LLAvatarListItemRemoveTimer +	 *  +	 * Implements a timer that removes avatar list item of a participant +	 * who has left the call. +	 */ +	class LLAvatarListItemRemoveTimer : public LLEventTimer +	{ +	public: +		typedef boost::function<void(const LLUUID&)> callback_t; + +		LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id); +		virtual ~LLAvatarListItemRemoveTimer() {}; + +		virtual BOOL tick(); + +	private: +		callback_t		mRemoveCallback; +		LLUUID			mSpeakerId; +	}; + +	typedef std::pair<LLUUID, LLAvatarListItemRemoveTimer*> timer_pair; +	typedef std::map<LLUUID, LLAvatarListItemRemoveTimer*> timers_map; + +	timers_map		mVoiceLeftTimersMap; +	S32				mVoiceLeftRemoveDelay;  }; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 7a83299dac..b1ddddc4b1 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -44,6 +44,8 @@  #include "llfloaterreg.h"  #include "llmutelist.h"  #include "llstylemap.h" +#include "lllayoutstack.h" +#include "llagent.h"  #include "llsidetray.h"//for blocked objects panel @@ -346,18 +348,23 @@ protected:  LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) -: LLTextEditor(p), -mMessageHeaderFilename(p.message_header), -mMessageSeparatorFilename(p.message_separator), -mLeftTextPad(p.left_text_pad), -mRightTextPad(p.right_text_pad), -mLeftWidgetPad(p.left_widget_pad), -mRightWidgetPad(p.right_widget_pad), -mTopSeparatorPad(p.top_separator_pad), -mBottomSeparatorPad(p.bottom_separator_pad), -mTopHeaderPad(p.top_header_pad), -mBottomHeaderPad(p.bottom_header_pad) +:	LLUICtrl(p), +	mMessageHeaderFilename(p.message_header), +	mMessageSeparatorFilename(p.message_separator), +	mLeftTextPad(p.left_text_pad), +	mRightTextPad(p.right_text_pad), +	mLeftWidgetPad(p.left_widget_pad), +	mRightWidgetPad(p.right_widget_pad), +	mTopSeparatorPad(p.top_separator_pad), +	mBottomSeparatorPad(p.bottom_separator_pad), +	mTopHeaderPad(p.top_header_pad), +	mBottomHeaderPad(p.bottom_header_pad)  { +	LLTextEditor::Params editor_params(p); +	editor_params.rect = getLocalRect(); +	editor_params.follows.flags = FOLLOWS_ALL; +	editor_params.enabled = false; // read only +	mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this);  }  LLChatHistory::~LLChatHistory() @@ -365,6 +372,49 @@ LLChatHistory::~LLChatHistory()  	this->clear();  } +void LLChatHistory::initFromParams(const LLChatHistory::Params& p) +{ +	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + +	LLRect stack_rect = getLocalRect(); +	stack_rect.mRight -= scrollbar_size; +	LLLayoutStack::Params layout_p; +	layout_p.rect = stack_rect; +	layout_p.follows.flags = FOLLOWS_ALL; +	layout_p.orientation = "vertical"; +	layout_p.mouse_opaque = false; +	 +	LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p, this); +	 +	const S32 NEW_TEXT_NOTICE_HEIGHT = 20; +	 +	LLPanel::Params panel_p; +	panel_p.name = "spacer"; +	panel_p.background_visible = false; +	panel_p.has_border = false; +	panel_p.mouse_opaque = false; +	stackp->addPanel(LLUICtrlFactory::create<LLPanel>(panel_p), 0, 30, true, false, LLLayoutStack::ANIMATE); + +	panel_p.name = "new_text_notice_holder"; +	LLRect new_text_notice_rect = getLocalRect(); +	new_text_notice_rect.mTop = new_text_notice_rect.mBottom + NEW_TEXT_NOTICE_HEIGHT; +	panel_p.rect = new_text_notice_rect; +	panel_p.background_opaque = true; +	panel_p.background_visible = true; +	panel_p.visible = false; +	mMoreChatPanel = LLUICtrlFactory::create<LLPanel>(panel_p); +	 +	LLTextBox::Params text_p(p.more_chat_text); +	text_p.rect = mMoreChatPanel->getLocalRect(); +	text_p.follows.flags = FOLLOWS_ALL; +	text_p.name = "more_chat_text"; +	mMoreChatText = LLUICtrlFactory::create<LLTextBox>(text_p, mMoreChatPanel); +	mMoreChatText->setClickedCallback(boost::bind(&LLChatHistory::onClickMoreText, this)); + +	stackp->addPanel(mMoreChatPanel, 0, 0, false, false, LLLayoutStack::ANIMATE); +} + +  /*void LLChatHistory::updateTextRect()  {  	static LLUICachedControl<S32> texteditor_border ("UITextEditorBorder", 0); @@ -393,15 +443,49 @@ LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style  	return header;  } +void LLChatHistory::onClickMoreText() +{ +	mEditor->endOfDoc(); +} +  void LLChatHistory::clear()  {  	mLastFromName.clear(); -	LLTextEditor::clear(); +	mEditor->clear();  	mLastFromID = LLUUID::null;  }  void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_chat_history, const LLStyle::Params& input_append_params)  { +	if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty()) +	{ +		mUnreadChatSources.insert(chat.mFromName); +		mMoreChatPanel->setVisible(TRUE); +		std::string chatters; +		for (unread_chat_source_t::iterator it = mUnreadChatSources.begin(); +			it != mUnreadChatSources.end();) +		{ +			chatters += *it; +			if (++it != mUnreadChatSources.end()) +			{ +				chatters += ","; +			} +		} +		LLStringUtil::format_map_t args; +		args["SOURCES"] = chatters; + +		if (mUnreadChatSources.size() == 1) +		{ +			mMoreChatText->setValue(LLTrans::getString("unread_chat_single", args)); +		} +		else +		{ +			mMoreChatText->setValue(LLTrans::getString("unread_chat_multiple", args)); +		} +		S32 height = mMoreChatText->getTextPixelHeight() + 5; +		mMoreChatPanel->reshape(mMoreChatPanel->getRect().getWidth(), height); +	} +  	LLColor4 txt_color = LLUIColorTable::instance().getColor("White");  	LLViewerChat::getChatColor(chat,txt_color);  	LLFontGL* fontp = LLViewerChat::getChatFont();	 @@ -416,7 +500,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  	if (use_plain_text_chat_history)  	{ -		appendText("[" + chat.mTimeStr + "] ", getText().size() != 0, style_params); +		mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, style_params);  		if (utf8str_trim(chat.mFromName).size() != 0)  		{ @@ -426,11 +510,11 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  				LLStyle::Params link_params(style_params);  				link_params.fillFrom(LLStyleMap::instance().lookupAgent(chat.mFromID));  				// Convert the name to a hotlink and add to message. -				appendText(chat.mFromName + ": ", false, link_params); +				mEditor->appendText(chat.mFromName + ": ", false, link_params);  			}  			else  			{ -				appendText(chat.mFromName + ": ", false, style_params); +				mEditor->appendText(chat.mFromName + ": ", false, style_params);  			}  		}  	} @@ -457,7 +541,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  		else  		{  			view = getHeader(chat, style_params); -			if (getText().size() == 0) +			if (mEditor->getText().size() == 0)  				p.top_pad = 0;  			else  				p.top_pad = mTopHeaderPad; @@ -467,9 +551,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  		p.view = view;  		//Prepare the rect for the view -		LLRect target_rect = getDocumentView()->getRect(); +		LLRect target_rect = mEditor->getDocumentView()->getRect();  		// squeeze down the widget by subtracting padding off left and right -		target_rect.mLeft += mLeftWidgetPad + mHPad; +		target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad();  		target_rect.mRight -= mRightWidgetPad;  		view->reshape(target_rect.getWidth(), view->getRect().getHeight());  		view->setOrigin(target_rect.mLeft, view->getRect().mBottom); @@ -478,7 +562,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  		if (utf8str_trim(chat.mFromName).size() != 0 && chat.mFromName != SYSTEM_FROM)  			header_text += chat.mFromName + ": "; -		appendWidget(p, header_text, false); +		mEditor->appendWidget(p, header_text, false);  		mLastFromName = chat.mFromName;  		mLastFromID = chat.mFromID;  		mLastMessageTime = new_message_time; @@ -490,10 +574,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  		style_params.font.style = "ITALIC";  		if (chat.mFromName.size() > 0) -			appendText(chat.mFromName + " ", TRUE, style_params); +			mEditor->appendText(chat.mFromName + " ", TRUE, style_params);  		// Ensure that message ends with NewLine, to avoid losing of new lines  		// while copy/paste from text chat. See EXT-3263. -		appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params); +		mEditor->appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params);  	}  	else  	{ @@ -504,8 +588,19 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  			// while copy/paste from text chat. See EXT-3263.  			message += NEW_LINE;  		} -		appendText(message, FALSE, style_params); +		mEditor->appendText(message, FALSE, style_params);  	} -	blockUndo(); +	mEditor->blockUndo(); +} + +void LLChatHistory::draw() +{ +	if (mEditor->scrolledToEnd()) +	{ +		mUnreadChatSources.clear(); +		mMoreChatPanel->setVisible(FALSE); +	} + +	LLUICtrl::draw();  } diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 8ca7dd1d58..260015e2dc 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -34,10 +34,11 @@  #define LLCHATHISTORY_H_  #include "lltexteditor.h" +#include "lltextbox.h"  #include "llviewerchat.h"  //Chat log widget allowing addition of a message as a widget  -class LLChatHistory : public LLTextEditor +class LLChatHistory : public LLUICtrl  {  	public:  		struct Params : public LLInitParam::Block<Params, LLTextEditor::Params> @@ -63,6 +64,8 @@ class LLChatHistory : public LLTextEditor  			//Header bottom padding  			Optional<S32>			bottom_header_pad; +			Optional<LLTextBox::Params>	more_chat_text; +  			Params()  			:	message_header("message_header"),  				message_separator("message_separator"), @@ -73,15 +76,16 @@ class LLChatHistory : public LLTextEditor  				top_separator_pad("top_separator_pad"),  				bottom_separator_pad("bottom_separator_pad"),  				top_header_pad("top_header_pad"), -				bottom_header_pad("bottom_header_pad") -				{ -				} +				bottom_header_pad("bottom_header_pad"), +				more_chat_text("more_chat_text") +			{}  		};  	protected:  		LLChatHistory(const Params&);  		friend class LLUICtrlFactory; +		/*virtual*/ void draw();  		/**  		 * Redefinition of LLTextEditor::updateTextRect() to considerate text  		 * left/right padding params. @@ -98,9 +102,13 @@ class LLChatHistory : public LLTextEditor  		 */  		LLView* getHeader(const LLChat& chat,const LLStyle::Params& style_params); +		void onClickMoreText(); +  	public:  		~LLChatHistory(); +		void initFromParams(const Params&); +  		/**  		 * Appends a widget message.  		 * If last user appended message, concurs with current user, @@ -129,5 +137,11 @@ class LLChatHistory : public LLTextEditor  		S32 mBottomSeparatorPad;  		S32 mTopHeaderPad;  		S32 mBottomHeaderPad; + +		LLPanel*		mMoreChatPanel; +		LLTextBox*		mMoreChatText; +		LLTextEditor*	mEditor; +		typedef std::set<std::string> unread_chat_source_t; +		unread_chat_source_t mUnreadChatSources;  };  #endif /* LLCHATHISTORY_H_ */ diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 21a0381495..c01202bb82 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -64,17 +64,6 @@ static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc");  static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script");  static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer"); -static const LLRect CHICLET_RECT(0, 25, 25, 0); -static const LLRect CHICLET_ICON_RECT(0, 22, 22, 0); -static const LLRect VOICE_INDICATOR_RECT(50, 25, 70, 0); -static const LLRect COUNTER_RECT(25, 25, 50, 0); -static const S32	OVERLAY_ICON_SHIFT = 2;	// used for shifting of an overlay icon for new massages in a chiclet - -// static -const S32 LLChicletPanel::s_scroll_ratio = 10; -const S32 LLChicletNotificationCounterCtrl::MAX_DISPLAYED_COUNT = 99; - -  boost::signals2::signal<LLChiclet* (const LLUUID&),  		LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > >  		LLIMChiclet::sFindChicletsSignal; @@ -140,7 +129,7 @@ private:  LLSysWellChiclet::Params::Params()  : button("button")  , unread_notifications("unread_notifications") -, max_displayed_count("max_displayed_count", 9) +, max_displayed_count("max_displayed_count", 99)  , flash_to_lit_count("flash_to_lit_count", 3)  , flash_period("flash_period", 0.5F)  { @@ -172,6 +161,9 @@ LLSysWellChiclet::~LLSysWellChiclet()  void LLSysWellChiclet::setCounter(S32 counter)  { +	// do nothing if the same counter is coming. EXT-3678. +	if (counter == mCounter) return; +  	// note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter)  	std::string s_count;  	if(counter != 0) @@ -186,9 +178,9 @@ void LLSysWellChiclet::setCounter(S32 counter)  	mButton->setLabel(s_count); -	setNewMessagesState(counter > 0); +	setNewMessagesState(counter > mCounter); -	// we have to flash to 'Lit' state each time new unread message is comming. +	// we have to flash to 'Lit' state each time new unread message is coming.  	if (counter > mCounter)  	{  		mFlashToLitTimer->flash(); @@ -387,9 +379,9 @@ void LLNotificationChiclet::createMenu()  //////////////////////////////////////////////////////////////////////////  LLChiclet::Params::Params() - : show_counter("show_counter") + : show_counter("show_counter", true) + , enable_counter("enable_counter", false)  { -	show_counter = true;  }  LLChiclet::LLChiclet(const Params& p) @@ -447,26 +439,12 @@ void LLChiclet::setValue(const LLSD& value)  LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)  : LLChiclet(p)  , mShowSpeaker(false) +, mDefaultWidth(p.rect().getWidth())  , mNewMessagesIcon(NULL)  , mSpeakerCtrl(NULL)  , mCounterCtrl(NULL)  { -	// initialize an overlay icon for new messages -	LLIconCtrl::Params icon_params; -	icon_params.visible = false; -	icon_params.image = LLUI::getUIImage(p.new_messages_icon_name); -	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(icon_params); -	addChild(mNewMessagesIcon); - -	// adjust size and position of an icon -	LLRect chiclet_rect = p.rect; -	LLRect overlay_icon_rect = LLRect(chiclet_rect.getWidth()/2, chiclet_rect.getHeight(), chiclet_rect.getWidth(), chiclet_rect.getHeight()/2);  -	mNewMessagesIcon->setRect(overlay_icon_rect); -	 -	// shift an icon a little bit to the right and up corner of a chiclet -	overlay_icon_rect.translate(OVERLAY_ICON_SHIFT, OVERLAY_ICON_SHIFT); - -	enableCounterControl(false); +	enableCounterControl(p.enable_counter);  }  void LLIMChiclet::setShowSpeaker(bool show) @@ -476,7 +454,6 @@ void LLIMChiclet::setShowSpeaker(bool show)  	{		  		mShowSpeaker = show;  		toggleSpeakerControl(); -		onChicletSizeChanged();		  	}  } @@ -501,7 +478,6 @@ void LLIMChiclet::setShowCounter(bool show)  	{		  		LLChiclet::setShowCounter(show);  		toggleCounterControl(); -		onChicletSizeChanged();		  	}  } @@ -514,32 +490,37 @@ void LLIMChiclet::setRequiredWidth()  {  	bool show_speaker = getShowSpeaker();  	bool show_counter = getShowCounter(); -	S32 required_width = CHICLET_RECT.getWidth(); +	S32 required_width = mDefaultWidth;  	if (show_counter)  	{ -		required_width += COUNTER_RECT.getWidth(); +		required_width += mCounterCtrl->getRect().getWidth();  	}  	if (show_speaker)  	{ -		required_width += VOICE_INDICATOR_RECT.getWidth(); +		required_width += mSpeakerCtrl->getRect().getWidth();  	}   	reshape(required_width, getRect().getHeight()); + +	onChicletSizeChanged();  }  void LLIMChiclet::toggleSpeakerControl()  {  	if(getShowSpeaker())  	{ +		// move speaker to the right of chiclet icon +		LLRect speaker_rc = mSpeakerCtrl->getRect(); +		speaker_rc.setLeftTopAndSize(mDefaultWidth, speaker_rc.mTop, speaker_rc.getWidth(), speaker_rc.getHeight()); +		mSpeakerCtrl->setRect(speaker_rc); +  		if(getShowCounter())  		{ -			mSpeakerCtrl->setRect(VOICE_INDICATOR_RECT); -		} -		else -		{ -			mSpeakerCtrl->setRect(COUNTER_RECT); +			// move speaker to the right of counter +			mSpeakerCtrl->translate(mCounterCtrl->getRect().getWidth(), 0);  		} +  		initSpeakerControl();		  	} @@ -566,6 +547,7 @@ void LLIMChiclet::setShowNewMessagesIcon(bool show)  	{  		mNewMessagesIcon->setVisible(show);  	} +	setRequiredWidth();  }  bool LLIMChiclet::getShowNewMessagesIcon() @@ -639,36 +621,9 @@ LLIMP2PChiclet::Params::Params()  : avatar_icon("avatar_icon")  , unread_notifications("unread_notifications")  , speaker("speaker") +, new_message_icon("new_message_icon")  , show_speaker("show_speaker")  { -	// *TODO Vadim: Get rid of hardcoded values. -	rect(CHICLET_RECT); - -	avatar_icon.name("avatar_icon"); -	avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - -	// *NOTE dzaporozhan -	// Changed icon height from 25 to 24 to fix ticket EXT-794. -	// In some cases(after changing UI scale) 25 pixel height icon was  -	// drawn incorrectly, i'm not sure why. -	avatar_icon.rect(CHICLET_ICON_RECT); -	avatar_icon.mouse_opaque(false); - -	unread_notifications.name("unread"); -	unread_notifications.font(LLFontGL::getFontSansSerif()); -	unread_notifications.font_halign(LLFontGL::HCENTER); -	unread_notifications.v_pad(5); -	unread_notifications.text_color(LLColor4::white); -	unread_notifications.mouse_opaque(false); -	unread_notifications.rect(COUNTER_RECT); -	unread_notifications.visible(false); - -	speaker.name("speaker"); -	speaker.rect(VOICE_INDICATOR_RECT); -	speaker.auto_update(true); -	speaker.draw_border(false); - -	show_speaker = false;  }  LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) @@ -676,6 +631,10 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)  , mChicletIconCtrl(NULL)  , mPopupMenu(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);  	addChild(mChicletIconCtrl); @@ -693,10 +652,6 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)  	sendChildToFront(mNewMessagesIcon);  	setShowSpeaker(p.show_speaker); - -	//since mShowSpeaker initialized with false  -	//setShowSpeaker(false) will not hide mSpeakerCtrl -	mSpeakerCtrl->setVisible(getShowSpeaker());  }  void LLIMP2PChiclet::initSpeakerControl() @@ -717,8 +672,11 @@ void LLIMP2PChiclet::updateMenuItems()  	if(getSessionId().isNull())  		return; +	LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId()); +	bool open_window_exists = open_im_floater && open_im_floater->getVisible(); +	mPopupMenu->getChild<LLUICtrl>("Send IM")->setEnabled(!open_window_exists); +	  	bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId()); -  	mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend);  } @@ -789,38 +747,10 @@ LLAdHocChiclet::Params::Params()  : avatar_icon("avatar_icon")  , unread_notifications("unread_notifications")  , speaker("speaker") +, new_message_icon("new_message_icon")  , show_speaker("show_speaker")  , avatar_icon_color("avatar_icon_color", LLColor4::green)  { -	// *TODO Vadim: Get rid of hardcoded values. -	rect(CHICLET_RECT); - -	avatar_icon.name("avatar_icon"); -	avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - -	// *NOTE dzaporozhan -	// Changed icon height from 25 to 24 to fix ticket EXT-794. -	// In some cases(after changing UI scale) 25 pixel height icon was  -	// drawn incorrectly, i'm not sure why. -	avatar_icon.rect(CHICLET_ICON_RECT); -	avatar_icon.mouse_opaque(false); - -	unread_notifications.name("unread"); -	unread_notifications.font(LLFontGL::getFontSansSerif()); -	unread_notifications.font_halign(LLFontGL::HCENTER); -	unread_notifications.v_pad(5); -	unread_notifications.text_color(LLColor4::white); -	unread_notifications.mouse_opaque(false); -	unread_notifications.rect(COUNTER_RECT); -	unread_notifications.visible(false); - - -	speaker.name("speaker"); -	speaker.rect(VOICE_INDICATOR_RECT); -	speaker.auto_update(true); -	speaker.draw_border(false); - -	show_speaker = false;  }  LLAdHocChiclet::LLAdHocChiclet(const Params& p) @@ -828,6 +758,10 @@ LLAdHocChiclet::LLAdHocChiclet(const Params& p)  , mChicletIconCtrl(NULL)  , mPopupMenu(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);  	//Make the avatar modified @@ -940,32 +874,9 @@ LLIMGroupChiclet::Params::Params()  : group_icon("group_icon")  , unread_notifications("unread_notifications")  , speaker("speaker") +, new_message_icon("new_message_icon")  , show_speaker("show_speaker")  { -	rect(CHICLET_RECT); - -	group_icon.name("group_icon"); -	 -	// *NOTE dzaporozhan -	// Changed icon height from 25 to 24 to fix ticket EXT-794. -	// In some cases(after changing UI scale) 25 pixel height icon was  -	// drawn incorrectly, i'm not sure why. -	group_icon.rect(CHICLET_ICON_RECT); - -	unread_notifications.name("unread"); -	unread_notifications.font(LLFontGL::getFontSansSerif()); -	unread_notifications.font_halign(LLFontGL::HCENTER); -	unread_notifications.v_pad(5); -	unread_notifications.text_color(LLColor4::white); -	unread_notifications.rect(COUNTER_RECT); -	unread_notifications.visible(false); - -	speaker.name("speaker"); -	speaker.rect(VOICE_INDICATOR_RECT); -	speaker.auto_update(true); -	speaker.draw_border(false); - -	show_speaker = false;  }  LLIMGroupChiclet::LLIMGroupChiclet(const Params& p) @@ -974,6 +885,10 @@ LLIMGroupChiclet::LLIMGroupChiclet(const Params& p)  , mChicletIconCtrl(NULL)  , mPopupMenu(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLChicletGroupIconCtrl::Params avatar_params = p.group_icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLChicletGroupIconCtrl>(avatar_params);  	addChild(mChicletIconCtrl); @@ -1062,6 +977,18 @@ void LLIMGroupChiclet::changed(LLGroupChange gc)  	}  } +void LLIMGroupChiclet::updateMenuItems() +{ +	if(!mPopupMenu) +		return; +	if(getSessionId().isNull()) +		return; + +	LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId()); +	bool open_window_exists = open_im_floater && open_im_floater->getVisible(); +	mPopupMenu->getChild<LLUICtrl>("Chat")->setEnabled(!open_window_exists); +} +  BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	if(!mPopupMenu) @@ -1071,6 +998,7 @@ BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)  	if (mPopupMenu)  	{ +		updateMenuItems();  		mPopupMenu->arrangeAndClear();  		LLMenuGL::showPopup(this, mPopupMenu, x, y);  	} @@ -1124,16 +1052,10 @@ void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data)  LLChicletPanel::Params::Params()  : chiclet_padding("chiclet_padding")  , scrolling_offset("scrolling_offset") +, scroll_button_hpad("scroll_button_hpad") +, scroll_ratio("scroll_ratio")  , min_width("min_width")  { -	chiclet_padding = 3; -	scrolling_offset = 40; - -	if (!min_width.isProvided()) -	{ -		// min_width = 4 chiclets + 3 paddings -		min_width = 180 + 3*chiclet_padding; -	}  };  LLChicletPanel::LLChicletPanel(const Params&p) @@ -1143,6 +1065,8 @@ LLChicletPanel::LLChicletPanel(const Params&p)  , mRightScrollButton(NULL)  , mChicletPadding(p.chiclet_padding)  , mScrollingOffset(p.scrolling_offset) +, mScrollButtonHPad(p.scroll_button_hpad) +, mScrollRatio(p.scroll_ratio)  , mMinWidth(p.min_width)  , mShowControls(true)  { @@ -1311,7 +1235,6 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)  		chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));  		arrange(); -		showScrollButtonsIfNeeded();  		return true;  	} @@ -1322,8 +1245,6 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)  void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)  {  	arrange(); -	trimChiclets(); -	showScrollButtonsIfNeeded();  }  void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m) @@ -1340,8 +1261,6 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)  	mChicletList.erase(it);  	arrange(); -	trimChiclets(); -	showScrollButtonsIfNeeded();  }  void LLChicletPanel::removeChiclet(S32 index) @@ -1434,8 +1353,6 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )  {  	LLPanel::reshape(width,height,called_from_parent); -	static const S32 SCROLL_BUTTON_PAD = 5; -  	//Needed once- to avoid error at first call of reshape() before postBuild()  	if(!mLeftScrollButton||!mRightScrollButton)  		return; @@ -1446,9 +1363,21 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )  	scroll_button_rect = mRightScrollButton->getRect();  	mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop,  		width, scroll_button_rect.mBottom)); -	mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, -		height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); +	 + +	bool need_show_scroll = needShowScroll(); +	if(need_show_scroll) +	{ +		mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad, +			height, width - scroll_button_rect.getWidth() - mScrollButtonHPad, 0)); +	} +	else +	{ +		mScrollArea->setRect(LLRect(0,height, width, 0)); +	} +	  	mShowControls = width >= mMinWidth; +	  	mScrollArea->setVisible(mShowControls);  	trimChiclets(); @@ -1456,13 +1385,27 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )  } +S32	LLChicletPanel::notifyParent(const LLSD& info) +{ +	if(info.has("notification")) +	{ +		std::string str_notification = info["notification"]; +		if(str_notification == "size_changes") +		{ +			arrange(); +			return 1; +		} +	} +	return LLPanel::notifyParent(info); +} +  void LLChicletPanel::arrange()  {  	if(mChicletList.empty())  		return; +	//initial arrange of chicklets positions  	S32 chiclet_left = getChiclet(0)->getRect().mLeft; -  	S32 size = getChicletCount();  	for( int n = 0; n < size; ++n)  	{ @@ -1476,6 +1419,24 @@ void LLChicletPanel::arrange()  		chiclet_left += chiclet_width + getChicletPadding();  	} + +	//reset size and pos on mScrollArea +	LLRect rect = getRect(); +	LLRect scroll_button_rect = mLeftScrollButton->getRect(); +	 +	bool need_show_scroll = needShowScroll(); +	if(need_show_scroll) +	{ +		mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad, +			rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - mScrollButtonHPad, 0)); +	} +	else +	{ +		mScrollArea->setRect(LLRect(0,rect.getHeight(), rect.getWidth(), 0)); +	} +	 +	trimChiclets(); +	showScrollButtonsIfNeeded();  }  void LLChicletPanel::trimChiclets() @@ -1493,6 +1454,17 @@ void LLChicletPanel::trimChiclets()  	}  } +bool LLChicletPanel::needShowScroll() +{ +	if(mChicletList.empty()) +		return false; +	 +	S32 chicklet_width  = (*mChicletList.rbegin())->getRect().mRight - (*mChicletList.begin())->getRect().mLeft; + +	return chicklet_width>getRect().getWidth(); +} + +  void LLChicletPanel::showScrollButtonsIfNeeded()  {  	bool can_scroll_left = canScrollLeft(); @@ -1620,7 +1592,7 @@ void LLChicletPanel::onRightScrollClick()  void LLChicletPanel::onLeftScrollHeldDown()  {  	S32 offset = mScrollingOffset; -	mScrollingOffset = mScrollingOffset / s_scroll_ratio; +	mScrollingOffset = mScrollingOffset / mScrollRatio;  	scrollLeft();  	mScrollingOffset = offset;  } @@ -1628,7 +1600,7 @@ void LLChicletPanel::onLeftScrollHeldDown()  void LLChicletPanel::onRightScrollHeldDown()  {  	S32 offset = mScrollingOffset; -	mScrollingOffset = mScrollingOffset / s_scroll_ratio; +	mScrollingOffset = mScrollingOffset / mScrollRatio;  	scrollRight();  	mScrollingOffset = offset;  } @@ -1690,7 +1662,7 @@ S32 LLChicletPanel::getTotalUnreadIMCount()  //////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////  LLChicletNotificationCounterCtrl::Params::Params() -: max_displayed_count("max_displayed_count", MAX_DISPLAYED_COUNT) +: max_displayed_count("max_displayed_count", 99)  {  } @@ -1767,6 +1739,7 @@ LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p)  : LLIconCtrl(p)  , mDefaultIcon(p.default_icon)  { +	setValue(LLUUID::null);  }  void LLChicletGroupIconCtrl::setValue(const LLSD& value ) @@ -1818,20 +1791,23 @@ LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p)  LLScriptChiclet::Params::Params()   : icon("icon") + , new_message_icon("new_message_icon")  { -	// *TODO Vadim: Get rid of hardcoded values. - 	rect(CHICLET_RECT); -	icon.rect(CHICLET_ICON_RECT);  }  LLScriptChiclet::LLScriptChiclet(const Params&p)   : LLIMChiclet(p)   , mChicletIconCtrl(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLIconCtrl::Params icon_params = p.icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params); -	// Let "new message" icon be on top, else it will be hidden behind chiclet icon. -	addChildInBack(mChicletIconCtrl); +	addChild(mChicletIconCtrl); + +	sendChildToFront(mNewMessagesIcon);  }  void LLScriptChiclet::setSessionId(const LLUUID& session_id) @@ -1870,20 +1846,24 @@ BOOL LLScriptChiclet::handleMouseDown(S32 x, S32 y, MASK mask)  static const std::string INVENTORY_USER_OFFER	("UserGiveItem");  LLInvOfferChiclet::Params::Params() + : icon("icon") + , new_message_icon("new_message_icon")  { -	// *TODO Vadim: Get rid of hardcoded values. -	rect(CHICLET_RECT); -	icon.rect(CHICLET_ICON_RECT);  }  LLInvOfferChiclet::LLInvOfferChiclet(const Params&p)   : LLIMChiclet(p)   , mChicletIconCtrl(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLChicletInvOfferIconCtrl::Params icon_params = p.icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLChicletInvOfferIconCtrl>(icon_params); -	// Let "new message" icon be on top, else it will be hidden behind chiclet icon. -	addChildInBack(mChicletIconCtrl); +	addChild(mChicletIconCtrl); + +	sendChildToFront(mNewMessagesIcon);  }  void LLInvOfferChiclet::setSessionId(const LLUUID& session_id) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 259476c2ad..ee9db10525 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -52,8 +52,6 @@ class LLChicletNotificationCounterCtrl : public LLTextBox  {  public: -	static const S32 MAX_DISPLAYED_COUNT; -  	struct Params :	public LLInitParam::Block<Params, LLTextBox::Params>  	{  		/** @@ -217,7 +215,8 @@ public:  	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>  	{ -		Optional<bool> show_counter; +		Optional<bool> show_counter, +					   enable_counter;  		Params();  	}; @@ -323,10 +322,7 @@ public:  	};  	struct Params : public LLInitParam::Block<Params, LLChiclet::Params>  	{ -		Optional<std::string> new_messages_icon_name; - -		Params() : new_messages_icon_name("new_messages_icon_name", "Unread_IM") -		{} +		Params(){}  	}; @@ -437,6 +433,8 @@ protected:  	bool mShowSpeaker;  	bool mCounterEnabled; +	/* initial width of chiclet, should not include counter or speaker width */ +	S32 mDefaultWidth;  	LLIconCtrl* mNewMessagesIcon;  	LLChicletNotificationCounterCtrl* mCounterCtrl; @@ -482,6 +480,8 @@ public:  		Optional<LLChicletSpeakerCtrl::Params> speaker; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Optional<bool>	show_speaker;  		Params(); @@ -521,6 +521,7 @@ protected:  	/**   	 * Enables/disables menus based on relationship with other participant. +	 * Enables/disables "show session" menu item depending on visible IM floater existence.  	 */  	virtual void updateMenuItems(); @@ -544,6 +545,8 @@ public:  		Optional<LLChicletSpeakerCtrl::Params> speaker; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Optional<bool>	show_speaker;  		Optional<LLColor4>	avatar_icon_color; @@ -614,6 +617,8 @@ public:  	{  		Optional<LLIconCtrl::Params> icon; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Params();  	}; @@ -654,6 +659,8 @@ public:  	{  		Optional<LLChicletInvOfferIconCtrl::Params> icon; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Params();  	}; @@ -697,6 +704,8 @@ public:  		Optional<LLChicletSpeakerCtrl::Params> speaker; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Optional<bool>	show_speaker;  		Params(); @@ -752,6 +761,11 @@ protected:  	virtual void onMenuItemClicked(const LLSD& user_data);  	/** +	 * Enables/disables "show session" menu item depending on visible IM floater existence. +	 */ +	virtual void updateMenuItems(); + +	/**  	 * Displays popup menu.  	 */  	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); @@ -931,7 +945,9 @@ public:  	struct Params :	public LLInitParam::Block<Params, LLPanel::Params>  	{  		Optional<S32> chiclet_padding, -					  scrolling_offset; +					  scrolling_offset, +					  scroll_button_hpad, +					  scroll_ratio;  		Optional<S32> min_width; @@ -1021,6 +1037,8 @@ public:  	S32 getTotalUnreadIMCount(); +	S32	notifyParent(const LLSD& info); +  protected:  	LLChicletPanel(const Params&p);  	friend class LLUICtrlFactory; @@ -1050,6 +1068,11 @@ protected:  	bool canScrollRight();  	/** +	 * Returns true if we need to show scroll buttons +	 */ +	bool needShowScroll(); + +	/**  	 * Returns true if chiclets can be scrolled left.  	 */  	bool canScrollLeft(); @@ -1143,6 +1166,8 @@ protected:  	S32 mChicletPadding;  	S32 mScrollingOffset; +	S32 mScrollButtonHPad; +	S32 mScrollRatio;  	S32 mMinWidth;  	bool mShowControls;  	static const S32 s_scroll_ratio; diff --git a/indra/newview/llcommanddispatcherlistener.cpp b/indra/newview/llcommanddispatcherlistener.cpp index 00a20de30e..91baeaf989 100644 --- a/indra/newview/llcommanddispatcherlistener.cpp +++ b/indra/newview/llcommanddispatcherlistener.cpp @@ -31,6 +31,11 @@ LLCommandDispatcherListener::LLCommandDispatcherListener(/* LLCommandDispatcher*          "[\"query\"] map of parameters, as if from ?key1=val&key2=val\n"          "[\"trusted\"] boolean indicating trusted browser [default true]",          &LLCommandDispatcherListener::dispatch); +    add("enumerate", +        "Post to [\"reply\"] a map of registered LLCommandHandler instances, containing\n" +        "name key and (e.g.) untrusted flag", +        &LLCommandDispatcherListener::enumerate, +        LLSD().with("reply", LLSD()));  }  void LLCommandDispatcherListener::dispatch(const LLSD& params) const @@ -45,3 +50,11 @@ void LLCommandDispatcherListener::dispatch(const LLSD& params) const      LLCommandDispatcher::dispatch(params["cmd"], params["params"], params["query"], NULL,                                    trusted_browser);  } + +void LLCommandDispatcherListener::enumerate(const LLSD& params) const +{ +    LLReqID reqID(params); +    LLSD response(LLCommandDispatcher::enumerate()); +    reqID.stamp(response); +    LLEventPumps::instance().obtain(params["reply"]).post(response); +} diff --git a/indra/newview/llcommanddispatcherlistener.h b/indra/newview/llcommanddispatcherlistener.h index d0070ddd71..9bcddebcc1 100644 --- a/indra/newview/llcommanddispatcherlistener.h +++ b/indra/newview/llcommanddispatcherlistener.h @@ -23,6 +23,7 @@ public:  private:      void dispatch(const LLSD& params) const; +    void enumerate(const LLSD& params) const;      //LLCommandDispatcher* mDispatcher;  }; diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 8c7e7bea83..dc506a1692 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -36,6 +36,7 @@  #include "llcommandhandler.h"  #include "llnotificationsutil.h"  #include "llcommanddispatcherlistener.h" +#include "stringize.h"  // system includes  #include <boost/tokenizer.hpp> @@ -67,6 +68,7 @@ public:  				  bool trusted_browser);  private: +	friend LLSD LLCommandDispatcher::enumerate();  	std::map<std::string, LLCommandHandlerInfo> mMap;  }; @@ -175,3 +177,56 @@ bool LLCommandDispatcher::dispatch(const std::string& cmd,  	return LLCommandHandlerRegistry::instance().dispatch(  		cmd, params, query_map, web, trusted_browser);  } + +static std::string lookup(LLCommandHandler::EUntrustedAccess value); + +LLSD LLCommandDispatcher::enumerate() +{ +	LLSD response; +	LLCommandHandlerRegistry& registry(LLCommandHandlerRegistry::instance()); +	for (std::map<std::string, LLCommandHandlerInfo>::const_iterator chi(registry.mMap.begin()), +																	 chend(registry.mMap.end()); +		 chi != chend; ++chi) +	{ +		LLSD info; +		info["untrusted"] = chi->second.mUntrustedBrowserAccess; +		info["untrusted_str"] = lookup(chi->second.mUntrustedBrowserAccess); +		response[chi->first] = info; +	} +	return response; +} + +/*------------------------------ lookup stuff ------------------------------*/ +struct symbol_info +{ +	const char* name; +	LLCommandHandler::EUntrustedAccess value; +}; + +#define ent(SYMBOL)										\ +	{													\ +		#SYMBOL + 28, /* skip "LLCommandHandler::UNTRUSTED_" prefix */	\ +		SYMBOL											\ +	} + +symbol_info symbols[] = +{ +	ent(LLCommandHandler::UNTRUSTED_ALLOW),		  // allow commands from untrusted browsers +	ent(LLCommandHandler::UNTRUSTED_BLOCK),		  // ignore commands from untrusted browsers +	ent(LLCommandHandler::UNTRUSTED_THROTTLE)	  // allow untrusted, but only a few per min. +}; + +#undef ent + +static std::string lookup(LLCommandHandler::EUntrustedAccess value) +{ +	for (symbol_info *sii(symbols), *siend(symbols + (sizeof(symbols)/sizeof(symbols[0]))); +		 sii != siend; ++sii) +	{ +		if (sii->value == value) +		{ +			return sii->name; +		} +	} +	return STRINGIZE("UNTRUSTED_" << value); +} diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h index 1bae6d9414..a1d4c880f5 100644 --- a/indra/newview/llcommandhandler.h +++ b/indra/newview/llcommandhandler.h @@ -34,6 +34,8 @@  #ifndef LLCOMMANDHANDLER_H  #define LLCOMMANDHANDLER_H +#include "llsd.h" +  /* Example:  secondlife:///app/foo/<uuid>     Command "foo" that takes one parameter, a UUID. @@ -103,6 +105,9 @@ public:  		// Execute a command registered via the above mechanism,  		// passing string parameters.  		// Returns true if command was found and executed correctly. +	/// Return an LLSD::Map of registered LLCommandHandlers and associated +	/// info (e.g. EUntrustedAccess). +	static LLSD enumerate();  };  #endif diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 0b27001f10..effa57b1ef 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -98,6 +98,7 @@ LLFastTimerView::LLFastTimerView(const LLRect& rect)  	mHoverBarIndex = -1;  	FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount();  	mPrintStats = -1;	 +	mAverageCyclesPerTimer = 0;  } @@ -306,8 +307,9 @@ void LLFastTimerView::draw()  	S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);  	S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f); -	// HACK: casting away const. Should use setRect or some helper function instead. -		const_cast<LLRect&>(getRect()).setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); +	LLRect new_rect; +	new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); +	setRect(new_rect);  	S32 left, top, right, bottom;  	S32 x, y, barw, barh, dx, dy; @@ -321,6 +323,10 @@ void LLFastTimerView::draw()  	S32 xleft = margin;  	S32 ytop = margin; +	mAverageCyclesPerTimer = llround(lerp((F32)mAverageCyclesPerTimer, (F32)(LLFastTimer::sTimerCycles / (U64)LLFastTimer::sTimerCalls), 0.1f)); +	LLFastTimer::sTimerCycles = 0; +	LLFastTimer::sTimerCalls = 0; +  	// Draw some help  	{ @@ -328,6 +334,10 @@ void LLFastTimerView::draw()  		y = height - ytop;  		texth = (S32)LLFontGL::getFontMonospace()->getLineHeight(); +#if TIME_FAST_TIMERS +		tdesc = llformat("Cycles per timer call: %d", mAverageCyclesPerTimer); +		LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); +#else  		char modedesc[][32] = {  			"2 x Average ",  			"Max         ", @@ -342,7 +352,6 @@ void LLFastTimerView::draw()  		tdesc = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]);  		LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); -  		textw = LLFontGL::getFontMonospace()->getWidth(tdesc);  		x = xleft, y -= (texth + 2); @@ -352,6 +361,7 @@ void LLFastTimerView::draw()  		LLFontGL::getFontMonospace()->renderUTF8(std::string("[Right-Click log selected] [ALT-Click toggle counts] [ALT-SHIFT-Click sub hidden]"),  										 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); +#endif  		y -= (texth + 2);  	} diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 2bb023ab14..f5c8f23818 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -91,6 +91,7 @@ private:  	S32 mHoverBarIndex;  	LLFrameTimer mHighlightTimer;  	S32 mPrintStats; +	S32 mAverageCyclesPerTimer;  };  #endif diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 832626e007..ee33c189f9 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -162,9 +162,22 @@ public:  		if (!region_name.empty())  		{  			LLToolTip::Params params; -			params.message = llformat("%s\n%s (%d, %d, %d)", getLabelSelected().c_str(), region_name.c_str(),  +			std::string extra_message = llformat("%s (%d, %d, %d)", region_name.c_str(),   				mLandmarkInfoGetter.getPosX(), mLandmarkInfoGetter.getPosY(), mLandmarkInfoGetter.getPosZ()); -			params.sticky_rect = calcScreenRect(); + +			params.message = llformat("%s\n%s", getLabelSelected().c_str(), extra_message.c_str()); +			 +			LLRect rect = calcScreenRect(); +			LLFontGL* standart_font = LLFontGL::getFontSansSerif(); +			if(standart_font) +			{ +				S32 w = llmax((S32)(standart_font->getWidthF32(getLabelSelected())+0.5),(S32)(standart_font->getWidthF32(extra_message)+0.5)); +				rect.mRight = rect.mLeft + w; +				params.max_width = w; +			} +			 +			params.sticky_rect = rect;  +  			LLToolTipMgr::instance().show(params);  		}  		return TRUE; @@ -984,7 +997,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)  	if (action == "open")  	{ -		teleport_via_landmark(item->getAssetUUID()); +		onButtonClick(item->getUUID());  	}  	else if (action == "about")  	{ diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index ff568a11a9..7e0e8bfaa7 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -760,8 +760,9 @@ void LLFloaterPreference::onClickResetCache()  	{  		gSavedSettings.setString("NewCacheLocation", "");  		gSavedSettings.setString("NewCacheLocationTopFolder", ""); -		LLNotificationsUtil::add("CacheWillBeMoved");  	} +	 +	LLNotificationsUtil::add("CacheWillBeMoved");  	std::string cache_location = gDirUtilp->getCacheDir(true);  	gSavedSettings.setString("CacheLocation", cache_location);  	std::string top_folder(gDirUtilp->getBaseFileName(cache_location)); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index dbecd45d1f..f53b62e490 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1379,7 +1379,6 @@ void LLFloaterSnapshot::Impl::onClickDiscard(void* data)  	if (view)  	{ -		view->getParent()->setMouseOpaque(FALSE);  		view->closeFloater();  	}  } @@ -2105,6 +2104,12 @@ void LLFloaterSnapshot::onOpen(const LLSD& key)  	gSnapshotFloaterView->adjustToFitScreen(this, FALSE);  } +void LLFloaterSnapshot::onClose(bool app_quitting) +{ +	getParent()->setMouseOpaque(FALSE); +} + +  //static   void LLFloaterSnapshot::update()  { diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index bd01f6c573..1333497bd2 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -52,6 +52,7 @@ public:  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void draw();  	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ void onClose(bool app_quitting);  	static void update(); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 8b05f8614d..474d2ca21f 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -751,7 +751,7 @@ void LLFolderView::sanitizeSelection()  		}  		// Don't allow invisible items (such as root folders) to be selected. -		if (item->getDontShowInHierarchy()) +		if (item->getHidden())  		{  			items_to_remove.push_back(item);  		} @@ -774,7 +774,7 @@ void LLFolderView::sanitizeSelection()  				parent_folder;  				parent_folder = parent_folder->getParentFolder())  			{ -				if (parent_folder->potentiallyVisible() && !parent_folder->getDontShowInHierarchy()) +				if (parent_folder->potentiallyVisible() && !parent_folder->getHidden())  				{  					// give initial selection to first ancestor folder that potentially passes the filter  					if (!new_selection) @@ -796,7 +796,7 @@ void LLFolderView::sanitizeSelection()  			// nothing selected to start with, so pick "My Inventory" as best guess  			new_selection = getItemByID(gInventory.getRootFolderID());  			// ... except if it's hidden from the UI. -			if (new_selection && new_selection->getDontShowInHierarchy()) +			if (new_selection && new_selection->getHidden())  			{  				new_selection = NULL;  			} @@ -1822,6 +1822,13 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data,  											 accept, tooltip_msg); +	// When there are no visible children drag and drop is handled +	// by the folder which is the hierarchy root. +	if (!handled && !hasVisibleChildren()) +	{ +		handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); +	} +  	if (handled)  	{  		lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index bfd9d6dca7..720c2c7b1a 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -136,7 +136,7 @@ LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p)  	mListener(p.listener),  	mArrowImage(p.folder_arrow_image),  	mBoxImage(p.selection_image), -	mDontShowInHierarchy(false), +	mHidden(false),  	mShowLoadStatus(false)  {  	refresh(); @@ -201,7 +201,7 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)  	LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children );  	// Skip over items that are invisible or are hidden from the UI. -	while(itemp && (!itemp->getVisible() || itemp->getDontShowInHierarchy())) +	while(itemp && (!itemp->getVisible() || itemp->getHidden()))  	{  		LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children );  		if (itemp == next_itemp)  @@ -418,7 +418,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)  S32 LLFolderViewItem::getItemHeight()  { -	if (mDontShowInHierarchy) return 0; +	if (mHidden) return 0;  	S32 icon_height = mIcon->getHeight();  	S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); @@ -823,7 +823,7 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  void LLFolderViewItem::draw()  { -	if (mDontShowInHierarchy) return; +	if (mHidden) return;  	static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);  	static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); @@ -970,11 +970,26 @@ void LLFolderViewItem::draw()  		font->renderUTF8( mLabel, 0, text_left, y, color, -				   LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -			S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); +						  LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, +						  S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); +//		LLViewerInventoryCategory *item = 0; +//		if (getListener()) +//			item = gInventory.getCategory(getListener()->getUUID()); +		bool root_is_loading = false; +		if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getRootFolderID())) +		{ +			// Descendent of my inventory. +			root_is_loading = gInventory.myInventoryFetchInProgress(); +		} +		if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getLibraryRootFolderID())) +		{ +			// Descendent of library +			root_is_loading = gInventory.libraryFetchInProgress(); +		} +			  		if ( (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) -			|| (LLInventoryModel::backgroundFetchActive() && mShowLoadStatus) ) +			|| (LLInventoryModel::backgroundFetchActive() && root_is_loading && mShowLoadStatus) )  		{  			std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) ";  			font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor, @@ -1257,7 +1272,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)  			// filter self only on first pass through  			LLFolderViewItem::filter( filter );  		} -		if (mDontShowInHierarchy) +		if (mHidden)  		{  			setOpen();  		} diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index a43096dcb2..21e24c2a4d 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -162,7 +162,7 @@ protected:  	LLUIImagePtr				mBoxImage;  	BOOL                        mIsLoading;  	LLTimer                     mTimeSinceRequestStart; -	bool						mDontShowInHierarchy; +	bool						mHidden;  	bool						mShowLoadStatus;  	// helper function to change the selection from the root. @@ -206,8 +206,11 @@ public:  	// makes sure that this view and it's children are the right size.  	virtual S32 arrange( S32* width, S32* height, S32 filter_generation );  	virtual S32 getItemHeight(); -	void setDontShowInHierarchy(bool dont_show) { mDontShowInHierarchy = dont_show; } -	bool getDontShowInHierarchy() const { return mDontShowInHierarchy; } + +	// Hide the folder from the UI, such as if you want to hide the root +	// folder in an inventory panel. +	void setHidden(bool hidden) { mHidden = hidden; } +	bool getHidden() const { return mHidden; }  	// applies filters to control visibility of inventory items  	virtual void filter( LLInventoryFilter& filter); diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index ff75d461df..7dd8ea694e 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -119,6 +119,31 @@ void LLGroupActions::search()  }  // static +void LLGroupActions::startCall(const LLUUID& group_id) +{ +	// create a new group voice session +	LLGroupData gdata; + +	if (!gAgent.getGroupData(group_id, gdata)) +	{ +		llwarns << "Error getting group data" << llendl; +		return; +	} + +	LLUUID session_id = gIMMgr->addSession(gdata.mName, IM_SESSION_GROUP_START, group_id, true); +	if (session_id == LLUUID::null) +	{ +		llwarns << "Error adding session" << llendl; +		return; +	} + +	// start the call +	gIMMgr->autoStartCallOnStartup(session_id); + +	make_ui_sound("UISndStartIM"); +} + +// static  void LLGroupActions::join(const LLUUID& group_id)  {  	LLGroupMgrGroupData* gdatap =  diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h index 9750b3e3cb..e99df86cd9 100644 --- a/indra/newview/llgroupactions.h +++ b/indra/newview/llgroupactions.h @@ -99,6 +99,11 @@ public:  	static bool isInGroup(const LLUUID& group_id);  	/** +	 * Start a group voice call. +	 */ +	static void startCall(const LLUUID& group_id); + +	/**  	 * Returns true if avatar is in group.  	 *  	 * Note that data about group members is loaded from server. diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index ab9db10f38..3ca459a403 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -37,6 +37,7 @@  // libs  #include "llbutton.h"  #include "lliconctrl.h" +#include "llmenugl.h"  #include "lltextbox.h"  #include "lltrans.h" @@ -46,6 +47,7 @@  #include "llfloaterreg.h"  #include "lltextutil.h"  #include "llviewercontrol.h"	// for gSavedSettings +#include "llviewermenu.h"		// for gMenuHolder  static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");  S32 LLGroupListItem::sIconWidth = 0; @@ -88,11 +90,24 @@ LLGroupList::LLGroupList(const Params& p)  	// Set default sort order.  	setComparator(&GROUP_COMPARATOR); + +	// Set up context menu. +	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + +	registrar.add("People.Groups.Action",			boost::bind(&LLGroupList::onContextMenuItemClick,	this, _2)); +	enable_registrar.add("People.Groups.Enable",	boost::bind(&LLGroupList::onContextMenuItemEnable,	this, _2)); + +	LLMenuGL* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups.xml", +			gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +	if(context_menu) +		mContextMenuHandle = context_menu->getHandle();  }  LLGroupList::~LLGroupList()  {  	gAgent.removeListener(this); +	LLView::deleteViewByHandle(mContextMenuHandle);  }  // virtual @@ -104,6 +119,22 @@ void LLGroupList::draw()  	LLFlatListView::draw();  } +// virtual +BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ +	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); + +	LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get(); +	if (context_menu) +	{ +		context_menu->buildDrawLabels(); +		context_menu->updateParent(LLMenuGL::sMenuContainer); +		LLMenuGL::showPopup(this, context_menu, x, y); +	} + +	return handled; +} +  void LLGroupList::setNameFilter(const std::string& filter)  {  	if (mNameFilter != filter) @@ -203,6 +234,46 @@ bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD&  	return false;  } +bool LLGroupList::onContextMenuItemClick(const LLSD& userdata) +{ +	std::string action = userdata.asString(); +	LLUUID selected_group = getSelectedUUID(); + +	if (action == "view_info") +	{ +		LLGroupActions::show(selected_group); +	} +	else if (action == "chat") +	{ +		LLGroupActions::startIM(selected_group); +	} +	else if (action == "call") +	{ +		LLGroupActions::startCall(selected_group); +	} +	else if (action == "activate") +	{ +		LLGroupActions::activate(selected_group); +	} +	else if (action == "leave") +	{ +		LLGroupActions::leave(selected_group); +	} + +	return true; +} + +bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata) +{ +	LLUUID selected_group_id = getSelectedUUID(); +	bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected + +	if (userdata.asString() == "activate") +		return real_group_selected && gAgent.getGroupID() != selected_group_id; + +	return real_group_selected; +} +  /************************************************************************/  /*          LLGroupListItem implementation                              */  /************************************************************************/ diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 33cfe005b9..f7afe0c0b2 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -60,6 +60,7 @@ public:  	virtual ~LLGroupList();  	virtual void draw(); // from LLView +	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView  	void setNameFilter(const std::string& filter);  	void toggleIcons(); @@ -71,6 +72,11 @@ private:  	void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM);  	bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes +	bool onContextMenuItemClick(const LLSD& userdata); +	bool onContextMenuItemEnable(const LLSD& userdata); + +	LLHandle<LLView>	mContextMenuHandle; +  	bool mShowIcons;  	bool mDirty;  	std::string mNameFilter; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index acaa6076f8..259f629bdd 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -45,6 +45,7 @@  #include "llfloaterchat.h"  #include "llfloaterreg.h"  #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container +#include "lllayoutstack.h"  #include "lllineeditor.h"  #include "lllogchat.h"  #include "llpanelimcontrolpanel.h" @@ -56,6 +57,7 @@  #include "llvoicechannel.h"  #include "lltransientfloatermgr.h"  #include "llinventorymodel.h" +#include "llrootview.h" @@ -107,6 +109,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  		default: break;  		}  	} +	setOverlapsScreenChannel(true);  }  void LLIMFloater::onFocusLost() @@ -220,6 +223,12 @@ LLIMFloater::~LLIMFloater()  //virtual  BOOL LLIMFloater::postBuild()  { +	// User-resizable control panels in P2P sessions look ugly (EXT-3470). +	if (mDialog == IM_NOTHING_SPECIAL || mDialog == IM_SESSION_P2P_INVITE) +	{ +		getChild<LLLayoutStack>("im_panels")->setPanelUserResize("panel_im_control_panel", FALSE); +	} +  	const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID);  	if (other_party_id.notNull())  	{ @@ -437,6 +446,16 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)  void LLIMFloater::getAllowedRect(LLRect& rect)  {  	rect = gViewerWindow->getWorldViewRectRaw(); +	static S32 right_padding = 0; +	if (right_padding == 0) +	{ +		LLPanel* side_bar_tabs = +				gViewerWindow->getRootView()->getChild<LLPanel> ( +						"side_bar_tabs"); +		right_padding = side_bar_tabs->getRect().getWidth(); +		LLTransientFloaterMgr::getInstance()->addControlView(side_bar_tabs); +	} +	rect.mRight -= right_padding;  }  void LLIMFloater::setDocked(bool docked, bool pop_on_undock) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index f5362acbfe..37ab144934 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -243,10 +243,13 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  	std::string joined_call = LLTrans::getString("joined_call");  	std::string other_avatar_name = ""; +	std::string message; +  	switch(mSessionType)  	{  	case AVALINE_SESSION: -		// *TODO: test avaline calls (EXT-2211) +		// no text notifications +		break;  	case P2P_SESSION:  		gCacheName->getFullName(mOtherParticipantID, other_avatar_name); @@ -255,10 +258,13 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CALL_STARTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, started_call); +				message = other_avatar_name + " " + started_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message); +				  				break;  			case LLVoiceChannel::STATE_CONNECTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), joined_call); +				message = you + " " + joined_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  			default:  				break;  			} @@ -268,37 +274,27 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CALL_STARTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), started_call); +				message = you + " " + started_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  				break;  			case LLVoiceChannel::STATE_CONNECTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, joined_call); +				message = other_avatar_name + " " + joined_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  			default:  				break;  			}  		} - -		// Update speakers list when connected -		if (LLVoiceChannel::STATE_CONNECTED == new_state) -		{ -			mSpeakers->update(true); -		} -  		break;  	case GROUP_SESSION:  	case ADHOC_SESSION: -		// *TODO: determine call starter's name "other_avatar_name" (EXT-2211) -		//        decide how to show notifications for a group/adhoc chat already opened -		//		  for now there is no notification from voice channel for this case  		if(direction == LLVoiceChannel::INCOMING_CALL)  		{  			switch(new_state)  			{ -			case LLVoiceChannel::STATE_CALL_STARTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, started_call); -				break;  			case LLVoiceChannel::STATE_CONNECTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), joined_call); +				message = you + " " + joined_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  			default:  				break;  			} @@ -308,19 +304,18 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CALL_STARTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), started_call); +				message = you + " " + started_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  				break;  			default:  				break;  			}  		} - -		// Update speakers list when connected -		if (LLVoiceChannel::STATE_CONNECTED == new_state) -		{ -			mSpeakers->update(true); -		} -		break; +	} +	// Update speakers list when connected +	if (LLVoiceChannel::STATE_CONNECTED == new_state) +	{ +		mSpeakers->update(true);  	}  } @@ -429,6 +424,61 @@ LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const  		(LLIMModel::LLIMSession*) NULL);  } +//*TODO consider switching to using std::set instead of std::list for holding LLUUIDs across the whole code +LLIMModel::LLIMSession* LLIMModel::findAdHocIMSession(const std::vector<LLUUID>& ids) +{ +	S32 num = ids.size(); +	if (!num) return NULL; + +	if (mId2SessionMap.empty()) return NULL; + +	std::map<LLUUID, LLIMSession*>::const_iterator it = mId2SessionMap.begin(); +	for (; it != mId2SessionMap.end(); ++it) +	{ +		LLIMSession* session = (*it).second; +	 +		if (!session->isAdHoc()) continue; +		if (session->mInitialTargetIDs.size() != num) continue; + +		std::list<LLUUID> tmp_list(session->mInitialTargetIDs.begin(), session->mInitialTargetIDs.end()); + +		std::vector<LLUUID>::const_iterator iter = ids.begin(); +		while (iter != ids.end()) +		{ +			tmp_list.remove(*iter); +			++iter; +			 +			if (tmp_list.empty())  +			{ +				break; +			} +		} + +		if (tmp_list.empty() && iter == ids.end()) +		{ +			return session; +		} +	} + +	return NULL; +} + +bool LLIMModel::LLIMSession::isAdHoc() +{ +	return IM_SESSION_CONFERENCE_START == mType || (IM_SESSION_INVITE == mType && !gAgent.isInGroup(mSessionID)); +} + +bool LLIMModel::LLIMSession::isP2P() +{ +	return IM_NOTHING_SPECIAL == mType; +} + +bool LLIMModel::LLIMSession::isOtherParticipantAvaline() +{ +	return !mOtherParticipantIsAvatar; +} + +  void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)  {  	LLIMSession* session = findIMSession(old_session_id); @@ -1227,15 +1277,15 @@ LLIMMgr::showSessionEventError(  	const std::string& error_string,  	const LLUUID session_id)  { -	const LLFloater* floater = getFloaterBySessionID (session_id); -	if (!floater) return; -  	LLSD args; +	LLStringUtil::format_map_t event_args; + +	event_args["RECIPIENT"] = LLIMModel::getInstance()->getName(session_id); +  	args["REASON"] =  		LLTrans::getString(error_string);  	args["EVENT"] = -		LLTrans::getString(event_string); -	args["RECIPIENT"] = floater->getTitle(); +		LLTrans::getString(event_string, event_args);  	LLNotificationsUtil::add(  		"ChatterBoxSessionEventError", @@ -1403,11 +1453,20 @@ void LLCallDialog::getAllowedRect(LLRect& rect)  	rect = gViewerWindow->getWorldViewRectScaled();  } -void LLCallDialog::onOpen(const LLSD& key) +BOOL LLCallDialog::postBuild()  { +	if (!LLDockableFloater::postBuild()) +		return FALSE; +  	// dock the dialog to the Speak Button, where other sys messages appear -	setDockControl(new LLDockControl(LLBottomTray::getInstance()->getChild<LLPanel>("speak_panel"), -		this, getDockTongue(), LLDockControl::TOP, boost::bind(&LLCallDialog::getAllowedRect, this, _1))); +	LLView *anchor_panel = LLBottomTray::getInstance()->getChild<LLView>("speak_panel"); + +	setDockControl(new LLDockControl( +		anchor_panel, this, +		getDockTongue(), LLDockControl::TOP, +		boost::bind(&LLCallDialog::getAllowedRect, this, _1))); + +	return TRUE;  }  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1423,13 +1482,17 @@ LLCallDialog(payload)  	}	  } -void LLOutgoingCallDialog::draw() +void LLCallDialog::draw()  {  	if (lifetimeHasExpired())  	{  		onLifetimeExpired();  	} -	LLDockableFloater::draw(); + +	if (getDockControl() != NULL) +	{ +		LLDockableFloater::draw(); +	}  }  bool LLOutgoingCallDialog::lifetimeHasExpired() @@ -1437,7 +1500,7 @@ bool LLOutgoingCallDialog::lifetimeHasExpired()  	if (mLifetimeTimer.getStarted())  	{  		F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32(); -		if (elapsed_time > LIFETIME)  +		if (elapsed_time > mLifetime)   		{  			return true;  		} @@ -1458,6 +1521,13 @@ void LLOutgoingCallDialog::show(const LLSD& key)  	// hide all text at first  	hideAllText(); +	// init notification's lifetime +	std::istringstream ss( getString("lifetime") ); +	if (!(ss >> mLifetime)) +	{ +		mLifetime = DEFAULT_LIFETIME; +	} +  	// customize text strings  	// tell the user which voice channel they are leaving  	if (!mPayload["old_channel_name"].asString().empty()) @@ -1551,7 +1621,7 @@ void LLOutgoingCallDialog::onCancel(void* user_data)  BOOL LLOutgoingCallDialog::postBuild()  { -	BOOL success = LLDockableFloater::postBuild(); +	BOOL success = LLCallDialog::postBuild();  	childSetAction("Cancel", onCancel, this); @@ -1568,14 +1638,50 @@ LLCallDialog(payload)  {  } +bool LLIncomingCallDialog::lifetimeHasExpired() +{ +	if (mLifetimeTimer.getStarted()) +	{ +		F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32(); +		if (elapsed_time > mLifetime)  +		{ +			return true; +		} +	} +	return false; +} + +void LLIncomingCallDialog::onLifetimeExpired() +{ +	// check whether a call is valid or not +	if (LLVoiceClient::getInstance()->findSession(mPayload["caller_id"].asUUID())) +	{ +		// restart notification's timer if call is still valid +		mLifetimeTimer.start(); +	} +	else +	{ +		// close invitation if call is already not valid +		mLifetimeTimer.stop(); +		closeFloater(); +	} +} +  BOOL LLIncomingCallDialog::postBuild()  { -	LLDockableFloater::postBuild(); +	LLCallDialog::postBuild();  	LLUUID session_id = mPayload["session_id"].asUUID();  	LLSD caller_id = mPayload["caller_id"];  	std::string caller_name = mPayload["caller_name"].asString(); +	// init notification's lifetime +	std::istringstream ss( getString("lifetime") ); +	if (!(ss >> mLifetime)) +	{ +		mLifetime = DEFAULT_LIFETIME; +	} +  	std::string call_type;  	if (gAgent.isInGroup(session_id))  	{ @@ -1606,13 +1712,30 @@ BOOL LLIncomingCallDialog::postBuild()  	LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");  	caller_name_widget->setValue(caller_name + " " + call_type);  	LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon"); -	icon->setValue(caller_id); +	if (is_avatar) +	{ +		icon->setValue(caller_id); +	} +	else +	{ +		icon->setValue("Avaline_Icon"); +	}  	childSetAction("Accept", onAccept, this);  	childSetAction("Reject", onReject, this);  	childSetAction("Start IM", onStartIM, this);  	childSetFocus("Accept"); +	if(mPayload["notify_box_type"] != "VoiceInviteGroup" && mPayload["notify_box_type"] != "VoiceInviteAdHoc") +	{ +		// starting notification's timer for P2P and AVALINE invitations +		mLifetimeTimer.start(); +	} +	else +	{ +		mLifetimeTimer.stop(); +	} +  	return TRUE;  } @@ -1743,6 +1866,14 @@ void LLIncomingCallDialog::processCallResponse(S32 response)  					new LLViewerChatterBoxInvitationAcceptResponder(  						session_id,  						inv_type)); + +				// send notification message to the corresponding chat  +				if (mPayload["notify_box_type"].asString() == "VoiceInviteGroup" || mPayload["notify_box_type"].asString() == "VoiceInviteAdHoc") +				{ +					std::string started_call = LLTrans::getString("started_call"); +					std::string message = mPayload["caller_name"].asString() + " " + started_call; +					LLIMModel::getInstance()->addMessageSilently(session_id, SYSTEM_FROM, LLUUID::null, message); +				}  			}  		}  		if (voice) @@ -2097,7 +2228,13 @@ BOOL LLIMMgr::getIMReceived() const  void LLIMMgr::autoStartCallOnStartup(const LLUUID& session_id)  {  	LLIMModel::LLIMSession *session = LLIMModel::getInstance()->findIMSession(session_id); -	if (session) +	if (!session) return; +	 +	if (session->mSessionInitialized) +	{ +		startCall(session_id); +	} +	else  	{  		session->mStartCallOnInitialize = true;  	}	 @@ -2159,12 +2296,22 @@ LLUUID LLIMMgr::addSession(  	bool new_session = !LLIMModel::getInstance()->findIMSession(session_id); +	//works only for outgoing ad-hoc sessions +	if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size()) +	{ +		LLIMModel::LLIMSession* ad_hoc_found = LLIMModel::getInstance()->findAdHocIMSession(ids); +		if (ad_hoc_found) +		{ +			new_session = false; +			session_id = ad_hoc_found->mSessionID; +		} +	} +  	if (new_session)  	{  		LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids, voice);  	} -  	//*TODO remove this "floater" thing when Communicate Floater's gone  	LLFloaterIMPanel* floater = findFloaterBySession(session_id);  	if(!floater) @@ -2394,6 +2541,11 @@ void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body  	if (speaker_mgr)  	{  		speaker_mgr->updateSpeakers(body); + +		// also the same call is added into LLVoiceClient::participantUpdatedEvent because +		// sometimes it is called AFTER LLViewerChatterBoxSessionAgentListUpdates::post() +		// when moderation state changed too late. See EXT-3544. +		speaker_mgr->update(true);  	}  	else  	{ diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 09f0c9df71..cec9d1642f 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -74,6 +74,10 @@ public:  		void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);  		static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata); +		bool isAdHoc(); +		bool isP2P(); +		bool isOtherParticipantAvaline(); +  		LLUUID mSessionID;  		std::string mName;  		EInstantMessage mType; @@ -133,6 +137,12 @@ public:  	 */  	LLIMSession* findIMSession(const LLUUID& session_id) const; +	/**  +	 * Find an Ad-Hoc IM Session with specified participants +	 * @return first found Ad-Hoc session or NULL if the session does not exist +	 */ +	LLIMSession* findAdHocIMSession(const std::vector<LLUUID>& ids); +  	/**  	 * Rebind session data to a new session id.  	 */ @@ -476,9 +486,20 @@ public:  	LLCallDialog(const LLSD& payload);  	~LLCallDialog() {} -	virtual void onOpen(const LLSD& key); +	virtual BOOL postBuild(); + +	// check timer state +	/*virtual*/ void draw();  protected: +	// lifetime timer for a notification +	LLTimer	mLifetimeTimer; +	// notification's lifetime in seconds +	S32		mLifetime; +	static const S32 DEFAULT_LIFETIME = 5; +	virtual bool lifetimeHasExpired() {return false;}; +	virtual void onLifetimeExpired() {}; +  	virtual void getAllowedRect(LLRect& rect);  	LLSD mPayload;  }; @@ -496,6 +517,8 @@ public:  	static void onStartIM(void* user_data);  private: +	/*virtual*/ bool lifetimeHasExpired(); +	/*virtual*/ void onLifetimeExpired();  	void processCallResponse(S32 response);  }; @@ -510,19 +533,11 @@ public:  	static void onCancel(void* user_data);  	static const LLUUID OCD_KEY; -	// check timer state -	/*virtual*/ void draw(); -  private: -  	// hide all text boxes  	void hideAllText(); -	// lifetime timer for NO_ANSWER notification -	LLTimer	mLifetimeTimer; -	// lifetime duration for NO_ANSWER notification -	static const S32 LIFETIME = 5; -	bool lifetimeHasExpired(); -	void onLifetimeExpired(); +	/*virtual*/ bool lifetimeHasExpired(); +	/*virtual*/ void onLifetimeExpired();  };  // Globals diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3fc2cbecbe..d70221b22a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4555,18 +4555,8 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod  	}  	else if (isRemoveAction(action))  	{ -		if (get_is_item_worn(mUUID)) -		{ -			LLViewerInventoryItem* item = getItem(); -			if (item) -			{ -				LLWearableList::instance().getAsset(item->getAssetUUID(), -													item->getName(), -													item->getType(), -													LLWearableBridge::onRemoveFromAvatarArrived, -													new OnRemoveStruct(mUUID)); -			} -		} +		removeFromAvatar(); +		return;  	}  	else LLItemBridge::performAction(folder, model, action);  } @@ -4949,6 +4939,66 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,  	delete on_remove_struct;  } +/* static */ +void LLWearableBridge::removeAllClothesFromAvatar() +{ +	// Remove COF links. +	for (S32 itype = WT_SHAPE; itype < WT_COUNT; ++itype) +	{ +		if (itype == WT_SHAPE || itype == WT_SKIN || itype == WT_HAIR || itype == WT_EYES) +			continue; + +		// MULTI-WEARABLES: fixed to index 0 +		LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>( +			gAgentWearables.getWearableInventoryItem((EWearableType)itype, 0)); +		if (!item) +			continue; +		const LLUUID &item_id = gInventory.getLinkedItemID(item->getUUID()); +		const LLWearable *wearable = gAgentWearables.getWearableFromItemID(item_id); +		if (!wearable) +			continue; + +		// Find and remove this item from the COF. +		LLInventoryModel::item_array_t items = gInventory.collectLinkedItems( +			item_id, LLAppearanceManager::instance().getCOF()); +		llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF. +		for (LLInventoryModel::item_array_t::const_iterator iter = items.begin(); +			 iter != items.end(); +			 ++iter) +		{ +			const LLViewerInventoryItem *linked_item = (*iter); +			const LLUUID &item_id = linked_item->getUUID(); +			gInventory.purgeObject(item_id); +		} +	} +	gInventory.notifyObservers(); + +	// Remove wearables from gAgentWearables +	LLAgentWearables::userRemoveAllClothes(); +} + +/* static */ +void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item) +{ +	if (item) +	{ +		LLWearableList::instance().getAsset(item->getAssetUUID(), +											item->getName(), +											item->getType(), +											LLWearableBridge::onRemoveFromAvatarArrived, +											new OnRemoveStruct(item->getUUID())); +	} +} + +void LLWearableBridge::removeFromAvatar() +{ +	if (get_is_item_worn(mUUID)) +	{ +		LLViewerInventoryItem* item = getItem(); +		removeItemFromAvatar(item); +	} +} +  LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,  													   const LLUUID& uuid,LLInventoryModel* model)  { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 4d83e9b684..cc1fa45b26 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -572,7 +572,10 @@ public:  	static BOOL		canRemoveFromAvatar( void* userdata );  	static void		onRemoveFromAvatar( void* userdata ); -	static void		onRemoveFromAvatarArrived( LLWearable* wearable, void* userdata ); +	static void		onRemoveFromAvatarArrived( LLWearable* wearable, 	void* userdata ); +	static void 	removeItemFromAvatar(LLViewerInventoryItem *item); +	static void 	removeAllClothesFromAvatar(); +	void			removeFromAvatar();  protected:  	LLWearableBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLAssetType::EType asset_type, LLInventoryType::EType inv_type, EWearableType  wearable_type) : diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 0a8108899a..711114173c 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -67,6 +67,7 @@ F32  LLInventoryModel::sMaxTimeBetweenFetches = 10.f;  BOOL LLInventoryModel::sTimelyFetchPending = FALSE;  LLFrameTimer LLInventoryModel::sFetchTimer;  S16 LLInventoryModel::sBulkFetchCount = 0; +BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE;  // Increment this if the inventory contents change in a non-backwards-compatible way.  // For viewer 2, the addition of link items makes a pre-viewer-2 cache incorrect. @@ -1339,8 +1340,7 @@ bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)  //Initialize statics.  bool LLInventoryModel::isBulkFetchProcessingComplete()  { -	return ( (sFetchQueue.empty()  -			&& sBulkFetchCount<=0)  ?  TRUE : FALSE ) ; +	return sFetchQueue.empty() && sBulkFetchCount<=0;  }  class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder @@ -1615,10 +1615,58 @@ void LLInventoryModel::bulkFetch(std::string url)  	}	  } +bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) +{ +	for (std::deque<LLUUID>::iterator it = sFetchQueue.begin(); +		 it != sFetchQueue.end(); ++it) +	{ +		const LLUUID& fetch_id = *it; +		if (gInventory.isObjectDescendentOf(fetch_id, cat_id)) +			return false; +	} +	return true; +} + +/* static */ +bool LLInventoryModel::libraryFetchStarted() +{ +	return sLibraryFetchStarted; +} + +/* static */ +bool LLInventoryModel::libraryFetchCompleted() +{ +	return libraryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getLibraryRootFolderID()); +} + +/* static */ +bool LLInventoryModel::libraryFetchInProgress() +{ +	return libraryFetchStarted() && !libraryFetchCompleted(); +} +	 +/* static */ +bool LLInventoryModel::myInventoryFetchStarted() +{ +	return sMyInventoryFetchStarted; +} + +/* static */ +bool LLInventoryModel::myInventoryFetchCompleted() +{ +	return myInventoryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getRootFolderID()); +} + +/* static */ +bool LLInventoryModel::myInventoryFetchInProgress() +{ +	return myInventoryFetchStarted() && !myInventoryFetchCompleted(); +} +  // static  bool LLInventoryModel::isEverythingFetched()  { -	return (sAllFoldersFetched ? true : false); +	return sAllFoldersFetched;  }  //static @@ -1637,7 +1685,6 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)  			if (!sMyInventoryFetchStarted)  			{  				sMyInventoryFetchStarted = TRUE; -				sFetchQueue.push_back(gInventory.getLibraryRootFolderID());  				sFetchQueue.push_back(gInventory.getRootFolderID());  				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);  			} @@ -1645,7 +1692,6 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)  			{  				sLibraryFetchStarted = TRUE;  				sFetchQueue.push_back(gInventory.getLibraryRootFolderID()); -				sFetchQueue.push_back(gInventory.getRootFolderID());  				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);  			}  		} @@ -2517,6 +2563,10 @@ void LLInventoryModel::buildParentChildMap()  		llwarns << "Found  " << lost << " lost categories." << llendl;  	} +	const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null); +	sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin(); + +  	// Now the items. We allocated in the last step, so now all we  	// have to do is iterate over the items and put them in the right  	// place. @@ -2604,6 +2654,33 @@ void LLInventoryModel::buildParentChildMap()  		cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);  		if(catsp)  		{ +			// *HACK - fix root inventory folder +			// some accounts has pbroken inventory root folders +			 +			std::string name = "My Inventory"; +			LLUUID prev_root_id = mRootFolderID; +			for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(), +					 it_end = mParentChildCategoryTree.end(); it != it_end; ++it) +			{ +				cat_array_t* cat_array = it->second; +				for (cat_array_t::const_iterator cat_it = cat_array->begin(), +						 cat_it_end = cat_array->end(); cat_it != cat_it_end; ++cat_it) +					{ +					LLPointer<LLViewerInventoryCategory> category = *cat_it; + +					if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY) +						continue; +					if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) +					{ +						if(category->getUUID()!=mRootFolderID) +						{ +							LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID); +							new_inv_root_folder_id = category->getUUID(); +						} +					} +				} +			} +  			// 'My Inventory',  			// root of the agent's inv found.  			// The inv tree is built. @@ -3530,6 +3607,19 @@ void LLInventoryModel::setLibraryOwnerID(const LLUUID& val)  	mLibraryOwnerID = val;  } +// static +BOOL LLInventoryModel::getIsFirstTimeInViewer2() +{ +	// Do not call this before parentchild map is built. +	if (!gInventory.mIsAgentInvUsable) +	{ +		llwarns << "Parent Child Map not yet built; guessing as first time in viewer2." << llendl; +		return TRUE; +	} + +	return sFirstTimeInViewer2; +} +  //----------------------------------------------------------------------------  // *NOTE: DEBUG functionality diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 27bbca493d..39377b4ae2 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -499,9 +499,9 @@ public:  	// *NOTE: DEBUG functionality  	void dumpInventory() const; -	//////////////////////////////////////////////////////////////////////////////// -	// Bulk / Background Fetch +	//////////////////////////////////////////////////////////////////////////////// +	// Bulk fetch  public:  	// Start and stop background breadth-first fetching of inventory contents.  	// This gets triggered when performing a filter-search @@ -516,6 +516,14 @@ public:  	// Add categories to a list to be fetched in bulk.  	static void bulkFetch(std::string url); +	static bool libraryFetchStarted(); +	static bool libraryFetchCompleted(); +	static bool libraryFetchInProgress(); +	 +	static bool myInventoryFetchStarted(); +	static bool myInventoryFetchCompleted(); +	static bool myInventoryFetchInProgress(); +	  private:   	static BOOL sMyInventoryFetchStarted;  	static BOOL sLibraryFetchStarted; @@ -525,6 +533,13 @@ private:  	// completing the fetch once per session should be sufficient  	static BOOL sBackgroundFetchActive;  	static S16 sBulkFetchCount; + +	//////////////////////////////////////////////////////////////////////////////// +	// Login status +public: +	static BOOL getIsFirstTimeInViewer2(); +private: +	static BOOL sFirstTimeInViewer2;  };  // a special inventory model for the agent diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 3c34ba32e2..164e72e621 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -402,9 +402,12 @@ void LLInventoryPanel::modelChanged(U32 mask)  // static  void LLInventoryPanel::onIdle(void *userdata)  { +	if (!gInventory.isInventoryUsable()) +		return; +  	LLInventoryPanel *self = (LLInventoryPanel*)userdata;  	// Inventory just initialized, do complete build -	if (!self->mViewsInitialized && gInventory.isInventoryUsable()) +	if (!self->mViewsInitialized)  	{  		self->initializeViews();  	} @@ -502,7 +505,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)  				// but still have the parent folder present for listener-related operations.  				if (id == mStartFolderID)  				{ -					folderp->setDontShowInHierarchy(TRUE); +					folderp->setHidden(TRUE);  				}  			}  		} @@ -625,9 +628,15 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  								   EAcceptance* accept,  								   std::string& tooltip_msg)  { -  	BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); +	// If folder view is empty the (x, y) point won't be in its rect +	// so the handler must be called explicitly. +	if (!mFolders->hasVisibleChildren()) +	{ +		handled = mFolders->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); +	} +  	if (handled)  	{  		mFolders->setDragAndDropThisFrame(); diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 2dc9f255d7..24c72c65ce 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -76,6 +76,7 @@ LLLoginInstance::LLLoginInstance() :  	mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1));  	mDispatcher.add("connect",    boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1));  	mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1)); +	mDispatcher.add("indeterminate", boost::bind(&LLLoginInstance::handleIndeterminate, this, _1));  }  LLLoginInstance::~LLLoginInstance() @@ -204,6 +205,8 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event)  		mTransferRate = event["transfer_rate"].asReal();  	} +	 +  	// Call the method registered in constructor, if any, for more specific  	// handling  	LLEventDispatcher::Callable method(mDispatcher.get(event["change"])); @@ -295,6 +298,22 @@ void LLLoginInstance::handleDisconnect(const LLSD& event)      // placeholder  } +void LLLoginInstance::handleIndeterminate(const LLSD& event) +{ +	// The indeterminate response means that the server +	// gave the viewer a new url and params to try. +	// The login module handles the retry, but it gives us the +	// server response so that we may show +	// the user some status. +	LLSD message = event.get("data").get("message"); +	if(message.isDefined()) +	{ +		LLSD progress_update; +		progress_update["desc"] = message; +		LLEventPumps::getInstance()->obtain("LLProgressView").post(progress_update); +	} +} +  bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)  {  	if(accepted) @@ -374,28 +393,6 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)  		mNotifications->add(notification_name, args, payload,   			boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2));  	} - -	/* *NOTE:Mani Experiment with Event API interface. -	if(!mUpdateAppResponse) -	{ -		bool make_unique = true; -		mUpdateAppResponse.reset(new LLEventStream("logininstance_updateapp", make_unique)); -		mUpdateAppResponse->listen("diaupdateDialogCallback",  -								   boost::bind(&LLLoginInstance::updateDialogCallback, -								 			   this, _1 -											   ) -								   ); -	} - -	LLSD event; -	event["op"] = "requestAdd"; -	event["name"] = notification_name; -	event["substitutions"] = args; -	event["payload"] = payload; -	event["reply"] = mUpdateAppResponse->getName(); - -	LLEventPumps::getInstance()->obtain("LLNotifications").post(event); -	*/  }  bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response) diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 19d7449bc1..c8704eddb4 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -89,6 +89,7 @@ private:  	void handleLoginFailure(const LLSD& event);  	void handleLoginSuccess(const LLSD& event);  	void handleDisconnect(const LLSD& event); +	void handleIndeterminate(const LLSD& event);  	bool handleTOSResponse(bool v, const std::string& key); @@ -107,7 +108,6 @@ private:  	std::string mSerialNumber;  	int mLastExecEvent;  	UpdaterLauncherCallback mUpdaterLauncher; -	boost::scoped_ptr<LLEventStream> mUpdateAppResponse;  	LLEventDispatcher mDispatcher;  }; diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index 2bb2a3da6f..b8da368bd7 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -164,7 +164,7 @@ void LLMediaDataClient::enqueue(const Request *request)  		// Sadly, we have to const-cast because items put into the queue are not const  		mSortedQueue.push_back(const_cast<LLMediaDataClient::Request*>(request)); -		LL_DEBUGS("LLMediaDataClient") << "SORTED queue:" << mSortedQueue << LL_ENDL; +		LL_DEBUGS("LLMediaDataClientQueue") << "SORTED queue:" << mSortedQueue << LL_ENDL;  	}  	else {  		if (mRoundRobinQueue.size() > mMaxRoundRobinQueueSize)  @@ -187,7 +187,7 @@ void LLMediaDataClient::enqueue(const Request *request)  			// Sadly, we have to const-cast because items put into the queue are not const  			mRoundRobinQueue.push_front(const_cast<LLMediaDataClient::Request*>(request)); -			LL_DEBUGS("LLMediaDataClient") << "RR queue:" << mRoundRobinQueue << LL_ENDL;			 +			LL_DEBUGS("LLMediaDataClientQueue") << "RR queue:" << mRoundRobinQueue << LL_ENDL;			  		}  		else  		{ @@ -226,16 +226,16 @@ bool LLMediaDataClient::processQueueTimer()  	{  		LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue size is:	  " << mSortedQueue.size()   			<< ", RR queue size is:	  " << mRoundRobinQueue.size() << LL_ENDL; -		LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue is:	  " << mSortedQueue << LL_ENDL; -		LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, RR queue is:	  " << mRoundRobinQueue << LL_ENDL; +		LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() started, SORTED queue is:	  " << mSortedQueue << LL_ENDL; +		LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() started, RR queue is:	  " << mRoundRobinQueue << LL_ENDL;  	}  	serviceQueue();  	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue size is:	  " << mSortedQueue.size()   		<< ", RR queue size is:	  " << mRoundRobinQueue.size() << LL_ENDL; -	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue is:	  " << mSortedQueue << LL_ENDL; -	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, RR queue is:	  " << mRoundRobinQueue << LL_ENDL; +	LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, SORTED queue is:	  " << mSortedQueue << LL_ENDL; +	LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, RR queue is:	  " << mRoundRobinQueue << LL_ENDL;  	return isEmpty();  } @@ -649,7 +649,7 @@ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)  /*virtual*/  void LLMediaDataClient::Responder::result(const LLSD& content)  { -	LL_DEBUGS("LLMediaDataClient") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL; +	LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL;  }  ////////////////////////////////////////////////////////////////////////////////////// @@ -703,7 +703,7 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)  	llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)  	if (type == LLMediaDataClient::Request::GET)  	{ -		LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL; +		LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL;  		// Look for an error  		if (content.has("error")) diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 22201aecb2..0ab3b07aea 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -571,7 +571,7 @@ BOOL LLPanelStandStopFlying::postBuild()  	mStandButton->setVisible(FALSE);  	mStopFlyingButton = getChild<LLButton>("stop_fly_btn"); -	mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE)); +	//mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE));  	mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this));  	mStopFlyingButton->setVisible(FALSE); @@ -684,7 +684,6 @@ void LLPanelStandStopFlying::onStopFlyingButtonClick()  	gAgent.setFlying(FALSE);  	setFocus(FALSE); // EXT-482 -	setVisible(FALSE);  }  /** diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 6210151d1b..71dc0f9011 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -51,6 +51,8 @@  #include "llsidetray.h"  #include "llslurl.h"  #include "llurlsimstring.h" +#include "llurlregistry.h" +#include "llurldispatcher.h"  #include "llviewerinventory.h"  #include "llviewermenu.h"  #include "llviewerparcelmgr.h" @@ -58,6 +60,7 @@  #include "llappviewer.h"  #include "llviewercontrol.h"  #include "llfloatermediabrowser.h" +#include "llweb.h"  #include "llinventorymodel.h"  #include "lllandmarkactions.h" @@ -543,7 +546,20 @@ void LLNavigationBar::onRegionNameResponse(  	// Invalid location?  	if (!region_handle)  	{ -		invokeSearch(typed_location); +		// handle any secondlife:// SLapps, or +		// display http:// URLs in the media browser, or +		// anything else is sent to the search floater +		if (LLUrlRegistry::instance().isUrl(typed_location)) +		{ +			if (! LLURLDispatcher::dispatchFromTextEditor(typed_location)) +			{ +				LLWeb::loadURL(typed_location); +			} +		} +		else +		{ +			invokeSearch(typed_location); +		}  		return;  	} diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 3a1ae5bf46..2ad82d3e8e 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -178,6 +178,8 @@ void	LLNearbyChat::addMessage(const LLChat& chat,bool archive)  	if (!chat.mMuted)  	{ +		tmp_chat.mFromName = chat.mFromID != gAgentID ? chat.mFromName : LLTrans::getString("You"); +  		if (chat.mChatStyle == CHAT_STYLE_IRC)  		{  			LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); @@ -196,7 +198,7 @@ void	LLNearbyChat::addMessage(const LLChat& chat,bool archive)  		}  		else  		{ -			mChatHistory->appendMessage(chat,use_plain_text_chat_history); +			mChatHistory->appendMessage(chat, use_plain_text_chat_history);  		}  	} diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 169560f688..9e13a626b4 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -335,7 +335,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg)  	if (tmp_chat.mChatStyle == CHAT_STYLE_IRC)  	{  		if(!tmp_chat.mFromName.empty()) -			tmp_chat.mText = tmp_chat.mFromName + " " + tmp_chat.mText.substr(3); +			tmp_chat.mText = tmp_chat.mFromName + tmp_chat.mText.substr(3);  		else  			tmp_chat.mText = tmp_chat.mText.substr(3);  	} diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index c3df4cbaf4..52de8355e9 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -93,6 +93,19 @@ bool LLAlertHandler::processNotification(const LLSD& notify)  	if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load")  	{ +		if (LLHandlerUtil::canSpawnSessionAndLogToIM(notification)) +		{ +			const std::string name = LLHandlerUtil::getSubstitutionName(notification); + +			LLUUID from_id = notification->getPayload()["from_id"]; + +			// firstly create session... +			LLHandlerUtil::spawnIMSession(name, from_id); + +			// ...then log message to have IM Well notified about new message +			LLHandlerUtil::logToIMP2P(notification); +		} +  		LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal);  		LLToast::Params p;  		p.notif_id = notification->getID(); diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 515c86bae8..0fb438bfe9 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -277,6 +277,13 @@ public:  	static bool canSpawnIMSession(const LLNotificationPtr& notification);  	/** +	 * Checks if passed notification can create IM session and be written into it. +	 * +	 * This method uses canLogToIM() & canSpawnIMSession(). +	 */ +	static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification); + +	/**  	 * Writes notification message to IM session.  	 */  	static void logToIM(const EInstantMessage& session_type, @@ -298,6 +305,20 @@ public:  	 * Writes notification message to nearby chat.  	 */  	static void logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type); + +	/** +	 * Spawns IM session. +	 */ +	static void spawnIMSession(const std::string& name, const LLUUID& from_id); + +	/** +	 * Returns name from the notification's substitution. +	 * +	 * Methods gets "NAME" or "[NAME]" from the substitution map. +	 * +	 * @param notification - Notification which substitution's name will be returned. +	 */ +	static std::string getSubstitutionName(const LLNotificationPtr& notification);  };  } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 5b54092c5c..fba5773602 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -47,11 +47,15 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),  				"ObjectGiveItem"), OBJECT_GIVE_ITEM_UNKNOWN_USER(  				"ObjectGiveItemUnknownUser"), PAYMENT_RECIVED("PaymentRecived"),  						ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), -						USER_GIVE_ITEM("UserGiveItem"), OFFER_FRIENDSHIP("OfferFriendship"), +						USER_GIVE_ITEM("UserGiveItem"), +						INVENTORY_ACCEPTED("InventoryAccepted"), +						INVENTORY_DECLINED("InventoryDeclined"), +						OFFER_FRIENDSHIP("OfferFriendship"),  						FRIENDSHIP_ACCEPTED("FriendshipAccepted"),  						FRIENDSHIP_OFFERED("FriendshipOffered"),  						FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), -						SERVER_OBJECT_MESSAGE("ServerObjectMessage"); +						SERVER_OBJECT_MESSAGE("ServerObjectMessage"), +						TELEPORT_OFFERED("TeleportOffered");  // static  bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) @@ -59,8 +63,11 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)  	return GRANTED_MODIFY_RIGHTS == notification->getName()  			|| REVOKED_MODIFY_RIGHTS == notification->getName()  			|| PAYMENT_RECIVED == notification->getName() +			|| OFFER_FRIENDSHIP == notification->getName()  			|| FRIENDSHIP_OFFERED == notification->getName() -			|| SERVER_OBJECT_MESSAGE == notification->getName(); +			|| SERVER_OBJECT_MESSAGE == notification->getName() +			|| INVENTORY_ACCEPTED == notification->getName() +			|| INVENTORY_DECLINED == notification->getName();  }  // static @@ -68,15 +75,25 @@ bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification)  {  	return notification->getType() == "notifytip"  			&&  FRIEND_ONLINE != notification->getName() -			&& FRIEND_OFFLINE != notification->getName(); +			&& FRIEND_OFFLINE != notification->getName() +			&& INVENTORY_ACCEPTED != notification->getName() +			&& INVENTORY_DECLINED != notification->getName();  }  // static  bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification)  { -	return ADD_FRIEND_WITH_MESSAGE == notification->getName() -			|| OFFER_FRIENDSHIP == notification->getName() -			|| FRIENDSHIP_ACCEPTED == notification->getName(); +	return OFFER_FRIENDSHIP == notification->getName() +			|| FRIENDSHIP_ACCEPTED == notification->getName() +			|| USER_GIVE_ITEM == notification->getName() +			|| INVENTORY_ACCEPTED == notification->getName() +			|| INVENTORY_DECLINED == notification->getName(); +} + +// static +bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification) +{ +	return canLogToIM(notification) && canSpawnIMSession(notification);  }  // static @@ -113,10 +130,7 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  // static  void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification)  { -	const std::string -			name = -					notification->getSubstitutions().has("NAME") ? notification->getSubstitutions()["NAME"] -							: notification->getSubstitutions()["[NAME]"]; +	const std::string name = LLHandlerUtil::getSubstitutionName(notification);  	const std::string session_name = notification->getPayload().has(  			"SESSION_NAME") ? notification->getPayload()["SESSION_NAME"].asString() : name; @@ -169,3 +183,23 @@ void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChat  	}  } +// static +void LLHandlerUtil::spawnIMSession(const std::string& name, const LLUUID& from_id) +{ +	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( +			session_id); +	if (session == NULL) +	{ +		LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL, from_id); +	} +} + +// static +std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notification) +{ +	return notification->getSubstitutions().has("NAME") +		? notification->getSubstitutions()["NAME"] +		: notification->getSubstitutions()["[NAME]"]; +} diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 4d64c5c0e4..dd66a6c507 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -105,22 +105,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  		{  			if (LLHandlerUtil::canSpawnIMSession(notification))  			{ -				const std::string name = notification->getSubstitutions().has( -						"NAME") ? notification->getSubstitutions()["NAME"] -						: notification->getSubstitutions()["[NAME]"]; +				const std::string name = LLHandlerUtil::getSubstitutionName(notification);  				LLUUID from_id = notification->getPayload()["from_id"]; -				LLUUID session_id = LLIMMgr::computeSessionID( -						IM_NOTHING_SPECIAL, from_id); - -				LLIMModel::LLIMSession* session = -						LLIMModel::instance().findIMSession(session_id); -				if (session == NULL) -				{ -					LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL, -							from_id); -				} +				LLHandlerUtil::spawnIMSession(name, from_id);  			}  			if (notification->getPayload().has("SUPPRES_TOST") diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 9afaddae82..83a2215ac6 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -101,6 +101,19 @@ bool LLTipHandler::processNotification(const LLSD& notify)  			}  		} +		const std::string name = notification->getSubstitutions()["NAME"]; +		LLUUID from_id = notification->getPayload()["from_id"]; +		if (LLHandlerUtil::canLogToIM(notification)) +		{ +			LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, name, name, +					notification->getMessage(), from_id, from_id); +		} + +		if (LLHandlerUtil::canSpawnIMSession(notification)) +		{ +			LLHandlerUtil::spawnIMSession(name, from_id); +		} +  		LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);  		LLToast::Params p; diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index fa16cb6473..63803469dd 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -64,10 +64,6 @@ LLOutputMonitorCtrl::Params::Params()  	auto_update("auto_update"),  	speaker_id("speaker_id")  { -	draw_border = true; -	name = "output_monitor"; -	follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP); -	mouse_opaque = false;  };  LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p) diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index ffe7f57167..913152e259 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -179,6 +179,10 @@ void LLPanelAvatarNotes::onOpen(const LLSD& key)  void LLPanelAvatarNotes::fillRightsData()  { +	childSetValue("status_check", FALSE); +	childSetValue("map_check", FALSE); +	childSetValue("objects_check", FALSE); +  	const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());  	// If true - we are viewing friend's profile, enable check boxes and set values.  	if(relation) @@ -403,6 +407,11 @@ void LLPanelProfileTab::updateButtons()  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// +bool enable_god() +{ +	return gAgent.isGodlike(); +} +  LLPanelAvatarProfile::LLPanelAvatarProfile()  : LLPanelProfileTab()  { @@ -423,6 +432,13 @@ BOOL LLPanelAvatarProfile::postBuild()  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;  	registrar.add("Profile.Pay",  boost::bind(&LLPanelAvatarProfile::pay, this));  	registrar.add("Profile.Share", boost::bind(&LLPanelAvatarProfile::share, this)); +	registrar.add("Profile.Kick", boost::bind(&LLPanelAvatarProfile::kick, this)); +	registrar.add("Profile.Freeze", boost::bind(&LLPanelAvatarProfile::freeze, this)); +	registrar.add("Profile.Unfreeze", boost::bind(&LLPanelAvatarProfile::unfreeze, this)); +	registrar.add("Profile.CSR", boost::bind(&LLPanelAvatarProfile::csr, this)); + +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; +	enable.add("Profile.EnableGod", boost::bind(&enable_god));  	mProfileMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); @@ -622,6 +638,28 @@ void LLPanelAvatarProfile::share()  	LLAvatarActions::share(getAvatarId());  } +void LLPanelAvatarProfile::kick() +{ +	LLAvatarActions::kick(getAvatarId()); +} + +void LLPanelAvatarProfile::freeze() +{ +	LLAvatarActions::freeze(getAvatarId()); +} + +void LLPanelAvatarProfile::unfreeze() +{ +	LLAvatarActions::unfreeze(getAvatarId()); +} + +void LLPanelAvatarProfile::csr() +{ +	std::string name; +	gCacheName->getFullName(getAvatarId(), name); +	LLAvatarActions::csr(getAvatarId(), name); +} +  void LLPanelAvatarProfile::onUrlTextboxClicked(const std::string& url)  {  	LLWeb::loadURL(url); diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index b19c5cca49..8f07c67fb1 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -181,6 +181,15 @@ protected:  	 */  	void share(); +	void kick(); +	void freeze(); +	void unfreeze(); +	void csr(); +	 + +	bool enableGod(); + +  	void onUrlTextboxClicked(const std::string& url);  	void onHomepageTextboxClicked();  	void onAddFriendButtonClick(); diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 0dae667e7f..e29320ffc2 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -1557,6 +1557,11 @@ void LLPanelClassifiedEdit::resetControls()  	childSetValue("price_for_listing", MINIMUM_PRICE_FOR_LISTING);  } +bool LLPanelClassifiedEdit::canClose() +{ +	return isValidName(); +} +  void LLPanelClassifiedEdit::sendUpdate()  {  	LLAvatarClassifiedInfo c_data; @@ -1671,6 +1676,12 @@ void LLPanelClassifiedEdit::onChange()  void LLPanelClassifiedEdit::onSaveClick()  { +	if(!isValidName()) +	{ +		notifyInvalidName(); +		return; +	} +  	sendUpdate();  	resetDirty();  } @@ -1681,6 +1692,34 @@ std::string LLPanelClassifiedEdit::getLocationNotice()  	return location_notice;  } +bool LLPanelClassifiedEdit::isValidName() +{ +	std::string name = getClassifiedName(); +	if (name.empty()) +	{ +		return false; +	} +	if (!isalnum(name[0])) +	{ +		return false; +	} + +	return true; +} + +void LLPanelClassifiedEdit::notifyInvalidName() +{ +	std::string name = getClassifiedName(); +	if (name.empty()) +	{ +		LLNotificationsUtil::add("BlankClassifiedName"); +	} +	else if (!isalnum(name[0])) +	{ +		LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); +	} +} +  void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)  {  	ctrl->setVisible(TRUE); diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h index 8b32495854..10fdf60bbe 100644 --- a/indra/newview/llpanelclassified.h +++ b/indra/newview/llpanelclassified.h @@ -305,6 +305,8 @@ public:  	bool isNew() { return mIsNew; } +	bool canClose(); +  protected:  	LLPanelClassifiedEdit(); @@ -325,6 +327,10 @@ protected:  	std::string getLocationNotice(); +	bool isValidName(); + +	void notifyInvalidName(); +  	void onSetLocationClick();  	void onChange();  	void onSaveClick(); diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 70e4798079..a8a75a1feb 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -65,7 +65,11 @@ void LLPanelChatControlPanel::onOpenVoiceControlsClicked()  void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)  { -	bool is_call_started = ( new_state >= LLVoiceChannel::STATE_CALL_STARTED ); +	updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED); +} + +void LLPanelChatControlPanel::updateButtons(bool is_call_started) +{  	childSetVisible("end_call_btn", is_call_started);  	childSetVisible("voice_ctrls_btn", is_call_started);  	childSetVisible("call_btn", ! is_call_started); @@ -112,6 +116,9 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)  	if(voice_channel)  	{  		mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2)); +		 +		//call (either p2p, group or ad-hoc) can be already in started state +		updateButtons(voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);  	}  } @@ -247,6 +254,9 @@ void LLPanelGroupControlPanel::draw()  	//Remove event does not raised until speakerp->mActivityTimer.hasExpired() is false, see LLSpeakerManager::update()  	//so we need update it to raise needed event  	mSpeakerManager->update(true); +	// Need to resort the participant list if it's in sort by recent speaker order. +	if (mParticipantList) +		mParticipantList->updateRecentSpeakersOrder();  	LLPanelChatControlPanel::draw();  } @@ -282,8 +292,9 @@ void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)  	mGroupID = LLIMModel::getInstance()->getOtherParticipantID(session_id); +	// for group and Ad-hoc chat we need to include agent into list   	if(!mParticipantList) -		mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list")); +		mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list"), true,false);  } diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index 711340efc7..c18be5a6df 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -57,6 +57,8 @@ public:  	virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); +	void updateButtons(bool is_call_started); +  	virtual void setSessionId(const LLUUID& session_id);  	const LLUUID& getSessionId() { return mSessionId; } diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 5de7c3f851..597b8bdb2d 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -81,7 +81,8 @@ BOOL LLPanelLandmarkInfo::postBuild()  	mCreator = getChild<LLTextBox>("creator");  	mCreated = getChild<LLTextBox>("created"); -	mTitleEditor = getChild<LLLineEditor>("title_editor"); +	mLandmarkTitle = getChild<LLTextBox>("title_value"); +	mLandmarkTitleEditor = getChild<LLLineEditor>("title_editor");  	mNotesEditor = getChild<LLTextEditor>("notes_editor");  	mFolderCombo = getChild<LLComboBox>("folder_combo"); @@ -101,7 +102,8 @@ void LLPanelLandmarkInfo::resetLocation()  	mCreator->setText(not_available);  	mOwner->setText(not_available);  	mCreated->setText(not_available); -	mTitleEditor->setText(LLStringUtil::null); +	mLandmarkTitle->setText(LLStringUtil::null); +	mLandmarkTitleEditor->setText(LLStringUtil::null);  	mNotesEditor->setText(LLStringUtil::null);  } @@ -122,7 +124,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type)  		case CREATE_LANDMARK:  			mCurrentTitle = getString("title_create_landmark"); -			mTitleEditor->setEnabled(TRUE); +			mLandmarkTitle->setVisible(FALSE); +			mLandmarkTitleEditor->setVisible(TRUE);  			mNotesEditor->setEnabled(TRUE);  		break; @@ -130,7 +133,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type)  		default:  			mCurrentTitle = getString("title_landmark"); -			mTitleEditor->setEnabled(FALSE); +			mLandmarkTitle->setVisible(TRUE); +			mLandmarkTitleEditor->setVisible(FALSE);  			mNotesEditor->setEnabled(FALSE);  		break;  	} @@ -185,12 +189,12 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data)  	{  		if (parcel_data.name.empty())  		{ -			mTitleEditor->setText(llformat("%s (%d, %d, %d)", +			mLandmarkTitleEditor->setText(llformat("%s (%d, %d, %d)",  								  parcel_data.sim_name.c_str(), region_x, region_y, region_z));  		}  		else  		{ -			mTitleEditor->setText(parcel_data.name); +			mLandmarkTitleEditor->setText(parcel_data.name);  		}  		std::string desc; @@ -281,7 +285,8 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem)  		mCreated->setText(timeStr);  	} -	mTitleEditor->setText(pItem->getName()); +	mLandmarkTitle->setText(pItem->getName()); +	mLandmarkTitleEditor->setText(pItem->getName());  	mNotesEditor->setText(pItem->getDescription());  } @@ -296,11 +301,14 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)  	else  	{  		mTitle->setText(mCurrentTitle); + +		mLandmarkTitle->setText(mLandmarkTitleEditor->getText());  	}  	if (mNotesEditor->getReadOnly() ==  (enabled == TRUE))  	{ -		mTitleEditor->setEnabled(enabled); +		mLandmarkTitle->setVisible(!enabled); +		mLandmarkTitleEditor->setVisible(enabled);  		mNotesEditor->setReadOnly(!enabled);  		mFolderCombo->setVisible(enabled);  		getChild<LLTextBox>("folder_label")->setVisible(enabled); @@ -313,7 +321,7 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)  const std::string& LLPanelLandmarkInfo::getLandmarkTitle() const  { -	return mTitleEditor->getText(); +	return mLandmarkTitleEditor->getText();  }  const std::string LLPanelLandmarkInfo::getLandmarkNotes() const @@ -333,7 +341,7 @@ BOOL LLPanelLandmarkInfo::setLandmarkFolder(const LLUUID& id)  void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id)  { -	std::string name = mTitleEditor->getText(); +	std::string name = mLandmarkTitleEditor->getText();  	std::string desc = mNotesEditor->getText();  	LLStringUtil::trim(name); diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h index 73e0ddb9cc..2a9949ae41 100644 --- a/indra/newview/llpanellandmarkinfo.h +++ b/indra/newview/llpanellandmarkinfo.h @@ -77,7 +77,8 @@ private:  	LLTextBox*			mOwner;  	LLTextBox*			mCreator;  	LLTextBox*			mCreated; -	LLLineEditor*		mTitleEditor; +	LLTextBox*			mLandmarkTitle; +	LLLineEditor*		mLandmarkTitleEditor;  	LLTextEditor*		mNotesEditor;  	LLComboBox*			mFolderCombo;  }; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index e16bac2098..87abb16395 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -49,9 +49,9 @@  #include "llfloaterworldmap.h"  #include "llfolderviewitem.h"  #include "llinventorypanel.h" -#include "llinventorysubtreepanel.h"  #include "lllandmarkactions.h"  #include "llplacesinventorybridge.h" +#include "llplacesinventorypanel.h"  #include "llsidetray.h"  #include "llviewermenu.h"  #include "llviewerregion.h" @@ -66,15 +66,54 @@ static const std::string TRASH_BUTTON_NAME = "trash_btn";  // helper functions -static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string); -static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list); +static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string); +static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);  /** - * Bridge to support knowing when the inventory has changed to update folder (open/close) state  - * for landmarks panels. - * - * Due to Inventory data are loaded in background we need to save folder state each time  - * next level is loaded. See EXT-3094. + * Functor counting expanded and collapsed folders in folder view tree to know + * when to enable or disable "Expand all folders" and "Collapse all folders" commands. + */ +class LLCheckFolderState : public LLFolderViewFunctor +{ +public: +	LLCheckFolderState() +	:	mCollapsedFolders(0), +		mExpandedFolders(0) +	{} +	virtual ~LLCheckFolderState() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item) {} +	S32 getCollapsedFolders() { return mCollapsedFolders; } +	S32 getExpandedFolders() { return mExpandedFolders; } + +private: +	S32 mCollapsedFolders; +	S32 mExpandedFolders; +}; + +// virtual +void LLCheckFolderState::doFolder(LLFolderViewFolder* folder) +{ +	// Counting only folders that pass the filter. +	// The listener check allow us to avoid counting the folder view +	// object itself because it has no listener assigned. +	if (folder->hasFilteredDescendants() && folder->getListener()) +	{ +		if (folder->isOpen()) +		{ +			++mExpandedFolders; +		} +		else +		{ +			++mCollapsedFolders; +		} +	} +} + +/** + * Bridge to support knowing when the inventory has changed to update Landmarks tab + * ShowFolderState filter setting to show all folders when the filter string is empty and + * empty folder message when Landmarks inventory category has no children.   */  class LLLandmarksPanelObserver : public LLInventoryObserver  { @@ -89,7 +128,7 @@ private:  void LLLandmarksPanelObserver::changed(U32 mask)  { -	mLP->saveFolderStateIfNoFilter(); +	mLP->updateShowFolderState();  }  LLLandmarksPanel::LLLandmarksPanel() @@ -134,22 +173,12 @@ BOOL LLLandmarksPanel::postBuild()  	getChild<LLAccordionCtrlTab>("tab_favorites")->setDisplayChildren(true);  	getChild<LLAccordionCtrlTab>("tab_landmarks")->setDisplayChildren(true); -	gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this);  	return TRUE;  }  // virtual  void LLLandmarksPanel::onSearchEdit(const std::string& string)  { -	// show all folders in Landmarks Accordion for empty filter -	if (mLandmarksInventoryPanel->getFilter()) -	{ -		mLandmarksInventoryPanel->setShowFolderState(string.empty() ? -			LLInventoryFilter::SHOW_ALL_FOLDERS : -			LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS -			); -	} -  	// give FolderView a chance to be refreshed. So, made all accordions visible  	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)  	{ @@ -162,7 +191,7 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string)  			tab->changeOpenClose(false);  		} -		LLInventorySubTreePanel* inventory_list = dynamic_cast<LLInventorySubTreePanel*>(tab->getAccordionView()); +		LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView());  		if (NULL == inventory_list) continue;  		if (inventory_list->getFilter()) @@ -173,6 +202,10 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string)  	if (sFilterSubString != string)  		sFilterSubString = string; + +	// show all folders in Landmarks Accordion for empty filter +	// only if Landmarks inventory folder is not empty +	updateShowFolderState();  }  // virtual @@ -226,7 +259,7 @@ void LLLandmarksPanel::updateVerbs()  	updateListCommands();  } -void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action) +void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)  {  	if (user_action && (items.size() > 0))  	{ @@ -254,12 +287,21 @@ void LLLandmarksPanel::onSelectorButtonClicked()  	}  } -void LLLandmarksPanel::saveFolderStateIfNoFilter() +void LLLandmarksPanel::updateShowFolderState()  { -	save_folder_state_if_no_filter(mFavoritesInventoryPanel); -	save_folder_state_if_no_filter(mLandmarksInventoryPanel); -	save_folder_state_if_no_filter(mMyInventoryPanel); -	save_folder_state_if_no_filter(mLibraryInventoryPanel); +	if (!mLandmarksInventoryPanel->getFilter()) +		return; + +	bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty(); +	if (show_all_folders) +	{ +		show_all_folders = category_has_descendents(mLandmarksInventoryPanel); +	} + +	mLandmarksInventoryPanel->setShowFolderState(show_all_folders ? +		LLInventoryFilter::SHOW_ALL_FOLDERS : +		LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS +		);  }  ////////////////////////////////////////////////////////////////////////// @@ -361,7 +403,7 @@ void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)  void LLLandmarksPanel::initFavoritesInventoryPanel()  { -	mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list"); +	mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list");  	initLandmarksPanel(mFavoritesInventoryPanel);  	mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems"); @@ -371,7 +413,7 @@ void LLLandmarksPanel::initFavoritesInventoryPanel()  void LLLandmarksPanel::initLandmarksInventoryPanel()  { -	mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list"); +	mLandmarksInventoryPanel = getChild<LLPlacesInventoryPanel>("landmarks_list");  	initLandmarksPanel(mLandmarksInventoryPanel); @@ -390,7 +432,7 @@ void LLLandmarksPanel::initLandmarksInventoryPanel()  void LLLandmarksPanel::initMyInventoryPanel()  { -	mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list"); +	mMyInventoryPanel= getChild<LLPlacesInventoryPanel>("my_inventory_list");  	initLandmarksPanel(mMyInventoryPanel); @@ -399,14 +441,14 @@ void LLLandmarksPanel::initMyInventoryPanel()  void LLLandmarksPanel::initLibraryInventoryPanel()  { -	mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list"); +	mLibraryInventoryPanel = getChild<LLPlacesInventoryPanel>("library_list");  	initLandmarksPanel(mLibraryInventoryPanel);  	initAccordion("tab_library", mLibraryInventoryPanel);  } -void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list)  {  	// In case of a dummy widget further we have no Folder View widget and no Filter,  	// so further initialization leads to crash. @@ -430,7 +472,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_lis  	inventory_list->saveFolderState();  } -void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list)  {  	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name); @@ -440,7 +482,7 @@ void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLIn  	accordion_tab->setDisplayChildren(false);  } -void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list)  {  	bool expanded = param.asBoolean(); @@ -466,7 +508,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInvento  	}  } -void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory_list)  {  	if (inventory_list != mFavoritesInventoryPanel)  	{ @@ -660,7 +702,12 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)  	}  	else if ("collapse_all" == command_name)  	{ -		root_folder->closeAllFolders(); +		root_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); + +		// The top level folder is invisible, it must be open to +		// display its sub-folders. +		root_folder->openTopLevelFolders(); +		root_folder->arrangeAll();  	}  	else if ( "sort_by_date" == command_name)  	{ @@ -722,6 +769,20 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  			return false;  	} +	LLCheckFolderState checker; +	rootFolderView->applyFunctorRecursively(checker); + +	// We assume that the root folder is always expanded so we enable "collapse_all" +	// command when we have at least one more expanded folder. +	if (checker.getExpandedFolders() < 2 && "collapse_all" == command_name) +	{ +		return false; +	} + +	if (checker.getCollapsedFolders() < 1 && "expand_all" == command_name) +	{ +		return false; +	}  	if("category" == command_name)  	{ @@ -778,46 +839,6 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata)  	}  } -void LLLandmarksPanel::updateFilteredAccordions() -{ -	LLInventoryPanel* inventory_list = NULL; -	LLAccordionCtrlTab* accordion_tab = NULL; -	bool needs_arrange = false; - -	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) -	{ -		accordion_tab = *iter; - -		accordion_tab->setVisible(TRUE); - -		inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView()); -		if (NULL == inventory_list) continue; - -		// This doesn't seem to work correctly.  Disabling for now. -Seraph -		// Enabled to show/hide accordions with/without landmarks. See EXT-2346. (Seth PE) -		LLFolderView* fv = inventory_list->getRootFolder(); - -		// arrange folder view contents to draw its descendants if it has any -		fv->arrangeFromRoot(); - -		bool has_descendants = fv->hasFilteredDescendants(); -		if (!has_descendants) -			needs_arrange = true; - -		accordion_tab->setVisible(has_descendants); - -		//accordion_tab->setVisible(TRUE); -	} - -	// we have to arrange accordion tabs for cases when filter string is less restrictive but -	// all items are still filtered. -	if (needs_arrange) -	{ -		static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion"); -		accordion->arrange(); -	} -} -  /*  Processes such actions: cut/rename/delete/paste actions @@ -926,13 +947,6 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg  	return true;  } -// static -void LLLandmarksPanel::doIdle(void* landmarks_panel) -{ -	LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel; -	panel->updateFilteredAccordions(); -} -  void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark)  {  	LLVector3d landmark_global_pos; @@ -1028,10 +1042,10 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)  //////////////////////////////////////////////////////////////////////////  // HELPER FUNCTIONS  ////////////////////////////////////////////////////////////////////////// -static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string) +static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string)  {  	// When search is cleared, restore the old folder state. -	if (string == "") +	if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "")  	{  		inventory_list->setFilterSubString(LLStringUtil::null);  		// Re-open folders that were open before @@ -1056,15 +1070,16 @@ static void filter_list(LLInventorySubTreePanel* inventory_list, const std::stri  	// Set new filter string  	inventory_list->setFilterSubString(string); -  } -static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list) +static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list)  { -	// save current folder open state if no filter currently applied -	if (inventory_list->getRootFolder() && inventory_list->getRootFolder()->getFilterSubString().empty()) +	LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getStartFolderID()); +	if (category)  	{ -		// inventory_list->saveFolderState(); // *TODO: commented out to fix build +		return category->getDescendentCount() > 0;  	} + +	return false;  }  // EOF diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index b0e537f647..569739237d 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -46,7 +46,7 @@ class LLAccordionCtrlTab;  class LLFolderViewItem;  class LLMenuGL;  class LLInventoryPanel; -class LLInventorySubTreePanel; +class LLPlacesInventoryPanel;  class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver  { @@ -60,17 +60,18 @@ public:  	/*virtual*/ void onTeleport();  	/*virtual*/ void updateVerbs(); -	void onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action); +	void onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);  	void onSelectorButtonClicked(); -	void setCurrentSelectedList(LLInventorySubTreePanel* inventory_list) +	void setCurrentSelectedList(LLPlacesInventoryPanel* inventory_list)  	{  		mCurrentSelectedList = inventory_list;  	}  	/** -	 * Saves folder state for all Inventory Panels if there are no applied filter. +	 * 	Update filter ShowFolderState setting to show empty folder message +	 *  if Landmarks inventory folder is empty.  	 */ -	void saveFolderStateIfNoFilter(); +	void updateShowFolderState();  protected:  	/** @@ -92,10 +93,10 @@ private:  	void initLandmarksInventoryPanel();  	void initMyInventoryPanel();  	void initLibraryInventoryPanel(); -	void initLandmarksPanel(LLInventorySubTreePanel* inventory_list); -	void initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list); -	void onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list); -	void deselectOtherThan(const LLInventorySubTreePanel* inventory_list); +	void initLandmarksPanel(LLPlacesInventoryPanel* inventory_list); +	void initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list); +	void onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list); +	void deselectOtherThan(const LLPlacesInventoryPanel* inventory_list);  	// List Commands Handlers  	void initListCommandsHandlers(); @@ -112,13 +113,6 @@ private:  	void onCustomAction(const LLSD& command_name);  	/** -	 * Updates accordions according to filtered items in lists. -	 * -	 * It hides accordion for empty lists -	 */ -	void updateFilteredAccordions(); - -	/**  	 * Determines if selected item can be modified via context/gear menu.  	 *  	 * It validates Places Landmarks rules first. And then LLFolderView permissions. @@ -133,11 +127,6 @@ private:  	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);  	/** -	 * Static callback for gIdleCallbacks to perform actions out of drawing -	 */ -	static void doIdle(void* landmarks_panel); - -	/**  	 * Landmark actions callbacks. Fire when a landmark is loaded from the list.  	 */  	void doShowOnMap(LLLandmark* landmark); @@ -148,14 +137,14 @@ private:  	void doCreatePick(LLLandmark* landmark);  private: -	LLInventorySubTreePanel*	mFavoritesInventoryPanel; -	LLInventorySubTreePanel*	mLandmarksInventoryPanel; -	LLInventorySubTreePanel*	mMyInventoryPanel; -	LLInventorySubTreePanel*	mLibraryInventoryPanel; +	LLPlacesInventoryPanel*	mFavoritesInventoryPanel; +	LLPlacesInventoryPanel*	mLandmarksInventoryPanel; +	LLPlacesInventoryPanel*	mMyInventoryPanel; +	LLPlacesInventoryPanel*	mLibraryInventoryPanel;  	LLMenuGL*					mGearLandmarkMenu;  	LLMenuGL*					mGearFolderMenu;  	LLMenuGL*					mMenuAdd; -	LLInventorySubTreePanel*	mCurrentSelectedList; +	LLPlacesInventoryPanel*	mCurrentSelectedList;  	LLInventoryObserver*		mInventoryObserver;  	LLPanel*					mListCommands; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index e134840153..5cc4d4aec6 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -564,6 +564,7 @@ BOOL LLPanelPeople::postBuild()  	buttonSetAction("chat_btn",			boost::bind(&LLPanelPeople::onChatButtonClicked,		this));  	buttonSetAction("im_btn",			boost::bind(&LLPanelPeople::onImButtonClicked,			this));  	buttonSetAction("call_btn",			boost::bind(&LLPanelPeople::onCallButtonClicked,		this)); +	buttonSetAction("group_call_btn",	boost::bind(&LLPanelPeople::onGroupCallButtonClicked,	this));  	buttonSetAction("teleport_btn",		boost::bind(&LLPanelPeople::onTeleportButtonClicked,	this));  	buttonSetAction("share_btn",		boost::bind(&LLPanelPeople::onShareButtonClicked,		this)); @@ -733,6 +734,7 @@ void LLPanelPeople::updateButtons()  	buttonSetVisible("view_profile_btn",	!group_tab_active);  	buttonSetVisible("im_btn",				!group_tab_active);  	buttonSetVisible("call_btn",			!group_tab_active); +	buttonSetVisible("group_call_btn",		group_tab_active);  	buttonSetVisible("teleport_btn",		friends_tab_active);  	buttonSetVisible("share_btn",			nearby_tab_active || friends_tab_active); @@ -781,6 +783,7 @@ void LLPanelPeople::updateButtons()  	bool none_group_selected = item_selected && selected_id.isNull();  	buttonSetEnabled("group_info_btn", !none_group_selected); +	buttonSetEnabled("group_call_btn", !none_group_selected);  	buttonSetEnabled("chat_btn", !none_group_selected);  } @@ -962,6 +965,13 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)  	mFilterSubString = search_upper; +	//store accordion tabs state before any manipulation with accordion tabs +	if(!mFilterSubString.empty()) +	{ +		notifyChildren(LLSD().with("action","store_state")); +	} + +  	// Apply new filter.  	mNearbyList->setNameFilter(mFilterSubString);  	mOnlineFriendList->setNameFilter(mFilterSubString); @@ -973,6 +983,12 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)  	setAccordionCollapsedByUser("tab_all", false);  	showFriendsAccordionsIfNeeded(); + +	//restore accordion tabs state _after_ all manipulations... +	if(mFilterSubString.empty()) +	{ +		notifyChildren(LLSD().with("action","restore_state")); +	}  }  void LLPanelPeople::onTabSelected(const LLSD& param) @@ -981,6 +997,8 @@ void LLPanelPeople::onTabSelected(const LLSD& param)  	mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME);  	updateButtons(); +	showFriendsAccordionsIfNeeded(); +  	if (GROUP_TAB_NAME == tab_name)  		mFilterEditor->setLabel(getString("groups_filter_label"));  	else @@ -1272,6 +1290,11 @@ void LLPanelPeople::onCallButtonClicked()  	}  } +void LLPanelPeople::onGroupCallButtonClicked() +{ +	LLGroupActions::startCall(getCurrentItemID()); +} +  void LLPanelPeople::onTeleportButtonClicked()  {  	LLAvatarActions::offerTeleport(getCurrentItemID()); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index f5cdc0935c..0d2bae1baf 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -100,6 +100,7 @@ private:  	void					onChatButtonClicked();  	void					onImButtonClicked();  	void					onCallButtonClicked(); +	void					onGroupCallButtonClicked();  	void					onTeleportButtonClicked();  	void					onShareButtonClicked();  	void					onMoreButtonClicked(); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 0314642d9e..c1c10e6022 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -184,8 +184,6 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)  	else if (item == std::string("can_call"))  	{  		bool result = false; -		int size = mUUIDs.size(); -		std::cout << size << std::endl;  		std::vector<LLUUID>::const_iterator  			id = mUUIDs.begin(),  			uuids_end = mUUIDs.end(); diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 839452d061..7a4dd3569d 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -284,6 +284,7 @@ void LLPanelPickInfo::setPickName(const std::string& name)  void LLPanelPickInfo::setPickDesc(const std::string& desc)  {  	childSetValue(XML_DESC, desc); +	updateContentPanelRect();  }  void LLPanelPickInfo::setPickLocation(const std::string& location) @@ -291,6 +292,31 @@ void LLPanelPickInfo::setPickLocation(const std::string& location)  	childSetValue(XML_LOCATION, location);  } +void LLPanelPickInfo::updateContentPanelRect() +{ +	LLTextBox* desc = getChild<LLTextBox>(XML_DESC); + +	S32 text_height = desc->getTextPixelHeight(); +	LLRect text_rect = desc->getRect(); + +	// let text-box height fit text height +	text_rect.set(text_rect.mLeft, text_rect.mTop, text_rect.mRight, text_rect.mTop - text_height); +	desc->setRect(text_rect); +	desc->reshape(text_rect.getWidth(), text_rect.getHeight()); +	// force reflow +	desc->setText(desc->getText()); + +	// bottom of description text-box will be bottom of content panel +	desc->localRectToOtherView(desc->getLocalRect(), &text_rect, getChild<LLView>("profile_scroll")); + +	LLPanel* content_panel = getChild<LLPanel>("scroll_content_panel"); +	LLRect content_rect = content_panel->getRect(); +	content_rect.set(content_rect.mLeft, content_rect.mTop, content_rect.mRight, text_rect.mBottom); +	// Somehow setRect moves all elements down. +	// Single reshape() updates rect and does not move anything. +	content_panel->reshape(content_rect.getWidth(), content_rect.getHeight()); +} +  void LLPanelPickInfo::onClickMap()  {  	LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 95add387d0..12b5a116b4 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -140,6 +140,15 @@ protected:  	virtual LLVector3d& getPosGlobal() { return mPosGlobal; }  	/** +	 * Reshapes content panel to fit all elements. +	 * +	 * Assume that description text-box is the last element of panel. +	 * Reshape text-box to fit text height and then reshape content panel to fit  +	 * text-box bottom. EXT-1326 +	 */ +	void updateContentPanelRect(); + +	/**  	 * Callback for "Map" button, opens Map  	 */  	void onClickMap(); diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 4d22d96072..751705dd57 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -485,6 +485,18 @@ void LLPanelPicks::onOpen(const LLSD& key)  	LLPanelProfileTab::onOpen(key);  } +void LLPanelPicks::onClosePanel() +{ +	if (mPanelClassifiedInfo) +	{ +		onPanelClassifiedClose(mPanelClassifiedInfo); +	} +	if (mPanelPickInfo) +	{ +		onPanelPickClose(mPanelPickInfo); +	} +} +  void LLPanelPicks::onListCommit(const LLFlatListView* f_list)  {  	// Make sure only one of the lists has selection. @@ -769,6 +781,11 @@ void LLPanelPicks::onPanelPickSave(LLPanel* panel)  void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel)  { +	if(!panel->canClose()) +	{ +		return; +	} +  	if(panel->isNew())  	{  		LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId()); diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index fd8a9e6938..1b2e35ca46 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -74,6 +74,8 @@ public:  	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ void onClosePanel(); +  	void processProperties(void* data, EAvatarProcessorType type);  	void updateData(); diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 596bd2909a..77c2fb7c8c 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -60,13 +60,18 @@ class LLTeleportHistoryFlatItem : public LLPanel  {  public:  	LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, const std::string &hl); -	virtual ~LLTeleportHistoryFlatItem() {}; +	virtual ~LLTeleportHistoryFlatItem();  	virtual BOOL postBuild(); +	/*virtual*/ S32 notify(const LLSD& info); +  	S32 getIndex() { return mIndex; }  	void setIndex(S32 index) { mIndex = index; }  	const std::string& getRegionName() { return mRegionName;} +	void setRegionName(const std::string& name); +	void setHighlightedText(const std::string& text); +	void updateTitle();  	/*virtual*/ void setValue(const LLSD& value); @@ -75,18 +80,51 @@ public:  	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);  	static void showPlaceInfoPanel(S32 index); + +	LLHandle<LLTeleportHistoryFlatItem> getItemHandle()	{ mItemHandle.bind(this); return mItemHandle; } +  private:  	void onProfileBtnClick();  	LLButton* mProfileBtn; +	LLTextBox* mTitle;  	LLTeleportHistoryPanel::ContextMenu *mContextMenu;  	S32 mIndex;  	std::string mRegionName;  	std::string mHighlight; +	LLRootHandle<LLTeleportHistoryFlatItem> mItemHandle;  }; +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> { +protected: +	typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t; + +public: +	LLTeleportHistoryFlatItem* getFlatItemForPersistentItem ( +		LLTeleportHistoryPanel::ContextMenu *context_menu, +		const LLTeleportHistoryPersistentItem& persistent_item, +		const S32 cur_item_index, +		const std::string &hl); + +	void removeItem(LLTeleportHistoryFlatItem* item); + +	void purge(); + +private: + +	flat_item_list_t mItems; +}; + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +  LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, const std::string &hl)  :	LLPanel(),  	mIndex(index), @@ -97,18 +135,37 @@ LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistor  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history_item.xml");  } +LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem() +{ +} +  //virtual  BOOL LLTeleportHistoryFlatItem::postBuild()  { -	LLTextUtil::textboxSetHighlightedVal(getChild<LLTextBox>("region"), LLStyle::Params(), mRegionName, mHighlight); +	mTitle = getChild<LLTextBox>("region");  	mProfileBtn = getChild<LLButton>("profile_btn");  	mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this)); +	updateTitle(); +  	return true;  } +S32 LLTeleportHistoryFlatItem::notify(const LLSD& info) +{ +	if(info.has("detach")) +	{ +		delete mMouseDownSignal; +		mMouseDownSignal = NULL; +		delete mRightMouseDownSignal; +		mRightMouseDownSignal = NULL; +		return 1; +	} +	return 0; +} +  void LLTeleportHistoryFlatItem::setValue(const LLSD& value)  {  	if (!value.isMap()) return;; @@ -116,6 +173,25 @@ void LLTeleportHistoryFlatItem::setValue(const LLSD& value)  	childSetVisible("selected_icon", value["selected"]);  } +void LLTeleportHistoryFlatItem::setHighlightedText(const std::string& text) +{ +	mHighlight = text; +} + +void LLTeleportHistoryFlatItem::setRegionName(const std::string& name) +{ +	mRegionName = name; +} + +void LLTeleportHistoryFlatItem::updateTitle() +{ +	LLTextUtil::textboxSetHighlightedVal( +		mTitle, +		LLStyle::Params(), +		mRegionName, +		mHighlight); +} +  void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)  {  	childSetVisible("hovered_icon", true); @@ -155,6 +231,82 @@ void LLTeleportHistoryFlatItem::onProfileBtnClick()  	LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);  } +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +LLTeleportHistoryFlatItem* +LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem ( +	LLTeleportHistoryPanel::ContextMenu *context_menu, +	const LLTeleportHistoryPersistentItem& persistent_item, +	const S32 cur_item_index, +	const std::string &hl) +{ +	LLTeleportHistoryFlatItem* item = NULL; +	if ( cur_item_index < (S32) mItems.size() ) +	{ +		item = mItems[cur_item_index].get(); +		if (item->getParent() == NULL) +		{ +			item->setIndex(cur_item_index); +			item->setRegionName(persistent_item.mTitle); +			item->setHighlightedText(hl); +			item->setVisible(TRUE); +			item->updateTitle(); +		} +		else +		{ +			// Item already added to parent +			item = NULL; +		} +	} + +	if ( !item ) +	{ +		item = new LLTeleportHistoryFlatItem(cur_item_index, +											 context_menu, +											 persistent_item.mTitle, +											 hl); +		mItems.push_back(item->getItemHandle()); +	} + +	return item; +} + +void LLTeleportHistoryFlatItemStorage::removeItem(LLTeleportHistoryFlatItem* item) +{ +	if (item) +	{ +		flat_item_list_t::iterator item_iter = std::find(mItems.begin(), +														 mItems.end(), +														 item->getItemHandle()); +		if (item_iter != mItems.end()) +		{ +			mItems.erase(item_iter); +		} +	} +} + +void LLTeleportHistoryFlatItemStorage::purge() +{ +	for ( flat_item_list_t::iterator +			  it = mItems.begin(), +			  it_end = mItems.end(); +		  it != it_end; ++it ) +	{ +		LLHandle <LLTeleportHistoryFlatItem> item_handle = *it; +		if ( !item_handle.isDead() && item_handle.get()->getParent() == NULL ) +		{ +			item_handle.get()->die(); +		} +	} +	mItems.clear(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +  LLTeleportHistoryPanel::ContextMenu::ContextMenu() :  	mMenu(NULL)  { @@ -236,6 +388,7 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()  LLTeleportHistoryPanel::~LLTeleportHistoryPanel()  { +	LLTeleportHistoryFlatItemStorage::instance().purge();  	LLView::deleteViewByHandle(mGearMenuHandle);  } @@ -478,16 +631,15 @@ void LLTeleportHistoryPanel::refresh()  	while (mCurrentItem >= 0)  	{  		// Filtering -		std::string landmark_title = items[mCurrentItem].mTitle; -		LLStringUtil::toUpper(landmark_title); - -		std::string::size_type match_offset = sFilterSubString.size() ? landmark_title.find(sFilterSubString) : std::string::npos; -		bool passed = sFilterSubString.size() == 0 || match_offset != std::string::npos; - -		if (!passed) +		if (!sFilterSubString.empty())  		{ -			mCurrentItem--; -			continue; +			std::string landmark_title(items[mCurrentItem].mTitle); +			LLStringUtil::toUpper(landmark_title); +			if( std::string::npos == landmark_title.find(sFilterSubString) ) +			{ +				mCurrentItem--; +				continue; +			}  		}  		// Checking whether date of item is earlier, than tab_boundary_date. @@ -507,6 +659,9 @@ void LLTeleportHistoryPanel::refresh()  			// Expand all accordion tabs when filtering  			if(!sFilterSubString.empty())  			{ +				//store accordion tab state when filter is not empty +				tab->notifyChildren(LLSD().with("action","store_state")); +				  				tab->setDisplayChildren(true);  			}  			// Restore each tab's expand state when not filtering @@ -514,6 +669,9 @@ void LLTeleportHistoryPanel::refresh()  			{  				bool collapsed = isAccordionCollapsedByUser(tab);  				tab->setDisplayChildren(!collapsed); +				 +				//restore accordion state after all those accodrion tabmanipulations +				tab->notifyChildren(LLSD().with("action","restore_state"));  			}  			curr_flat_view = getFlatListViewFromTab(tab); @@ -521,9 +679,14 @@ void LLTeleportHistoryPanel::refresh()  		if (curr_flat_view)  		{ -			LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle, sFilterSubString); -			curr_flat_view->addItem(item); - +			LLTeleportHistoryFlatItem* item = +				LLTeleportHistoryFlatItemStorage::instance() +				.getFlatItemForPersistentItem(&mContextMenu, +											  items[mCurrentItem], +											  mCurrentItem, +											  sFilterSubString); +			if ( !curr_flat_view->addItem(item, LLUUID::null, ADD_BOTTOM, false) ) +				llerrs << "Couldn't add flat item to teleport history." << llendl;  			if (mLastSelectedItemIndex == mCurrentItem)  				curr_flat_view->selectItem(item, true);  		} @@ -534,6 +697,16 @@ void LLTeleportHistoryPanel::refresh()  			break;  	} +	for (S32 n = mItemContainers.size() - 1; n >= 0; --n) +	{ +		LLAccordionCtrlTab* tab = mItemContainers.get(n); +		LLFlatListView* fv = getFlatListViewFromTab(tab); +		if (fv) +		{ +			fv->notify(LLSD().with("rearrange", LLSD())); +		} +	} +  	mHistoryAccordion->arrange();  	updateVerbs(); @@ -566,11 +739,12 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)  	}  	const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems(); -	LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(history_items.size(), // index will be decremented inside loop below -									&mContextMenu, -									history_items[history_items.size() - 1].mTitle, // Most recent item, it was -									sFilterSubString); -															 // added instead of removed +	LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance() +		.getFlatItemForPersistentItem(&mContextMenu, +									  history_items[history_items.size() - 1], // Most recent item, it was added instead of removed +									  history_items.size(), // index will be decremented inside loop below +									  sFilterSubString); +  	fv->addItem(item, LLUUID::null, ADD_TOP);  	// Index of each item, from last to removed item should be decremented @@ -598,6 +772,8 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)  			if (item->getIndex() == removed_index)  			{ +				LLTeleportHistoryFlatItemStorage::instance().removeItem(item); +  				fv->removeItem(item);  				// If flat list becames empty, then accordion tab should be hidden @@ -629,10 +805,12 @@ void LLTeleportHistoryPanel::showTeleportHistory()  		LLFlatListView* fv = getFlatListViewFromTab(tab);  		if (fv) -			fv->clear(); +		{ +			// Detached panels are managed by LLTeleportHistoryFlatItemStorage +			std::vector<LLPanel*> detached_items; +			fv->detachItems(detached_items); +		}  	} - -	refresh();  }  void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index afb9892d12..330e220af3 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -39,7 +39,6 @@  #include "llimview.h"  #include "llparticipantlist.h" -#include "llavatarlist.h"  #include "llspeakers.h"  #include "llviewermenu.h"  #include "llvoiceclient.h" @@ -51,12 +50,14 @@  static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list,  bool use_context_menu/* = true*/): +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list,  bool use_context_menu/* = true*/, +		bool exclude_agent /*= true*/):  	mSpeakerMgr(data_source),  	mAvatarList(avatar_list),  	mSortOrder(E_SORT_BY_NAME)  ,	mParticipantListMenu(NULL) -,	mExcludeAgent(true) +,	mExcludeAgent(exclude_agent) +,	mValidateSpeakerCallback(NULL)  {  	mSpeakerAddListener = new SpeakerAddListener(*this);  	mSpeakerRemoveListener = new SpeakerRemoveListener(*this); @@ -86,23 +87,23 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av  	}  	//Lets fill avatarList with existing speakers -	LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); -  	LLSpeakerMgr::speaker_list_t speaker_list;  	mSpeakerMgr->getSpeakerList(&speaker_list, true);  	for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)  	{  		const LLPointer<LLSpeaker>& speakerp = *it; -		addAvatarIDExceptAgent(group_members, speakerp->mID); +		addAvatarIDExceptAgent(speakerp->mID);  		if ( speakerp->mIsModerator )  		{  			mModeratorList.insert(speakerp->mID);  		} +		else +		{ +			mModeratorToRemoveList.insert(speakerp->mID); +		}  	}  	// we need to exclude agent id for non group chat -	mExcludeAgent = !gAgent.isInGroup(mSpeakerMgr->getSessionID()); -	mAvatarList->setDirty(true);  	sort();  } @@ -162,7 +163,7 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)  			{  				std::string name = item->getAvatarName();  				size_t found = name.find(moderator_indicator); -				if (found == std::string::npos) +				if (found != std::string::npos)  				{  					name.erase(found, moderator_indicator_len);  					item->setName(name); @@ -204,42 +205,37 @@ void LLParticipantList::setSortOrder(EParticipantSortOrder order)  	}  } -void LLParticipantList::refreshVoiceState() +LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder() +{ +	return mSortOrder; +} + +void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb)  { -	LLSpeakerMgr::speaker_list_t speakers; -	mSpeakerMgr->getSpeakerList(&speakers, TRUE); +	mValidateSpeakerCallback = cb; +} -	for (LLSpeakerMgr::speaker_list_t::iterator iter = speakers.begin(); -		iter != speakers.end(); ++iter) +void LLParticipantList::updateRecentSpeakersOrder() +{ +	if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())  	{ -		LLSpeaker* speakerp = (*iter).get(); -		const LLUUID& speaker_id = speakerp->mID; -		LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (mAvatarList->getItemByValue(speaker_id)); -		if ( item ) -		{ -			// if voice is disabled for this speaker show non voice speakers as disabled -			bool is_in_voice = speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE -				&& speakerp->mStatus != LLSpeaker::STATUS_MUTED; -			item->setOnline(!is_in_voice); -		} +		// Need to update speakers to sort list correctly +		mSpeakerMgr->update(true); +		// Resort avatar list +		sort();  	}  }  bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)  { -	LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();  	LLUUID uu_id = event->getValue().asUUID(); -	LLAvatarList::uuid_vector_t::iterator found = std::find(group_members.begin(), group_members.end(), uu_id); -	if(found != group_members.end()) +	if (mValidateSpeakerCallback && mValidateSpeakerCallback(uu_id))  	{ -		llinfos << "Already got a buddy" << llendl;  		return true;  	} -	addAvatarIDExceptAgent(group_members, uu_id); -	// Mark AvatarList as dirty one -	mAvatarList->setDirty(); +	addAvatarIDExceptAgent(uu_id);  	sort();  	return true;  } @@ -312,7 +308,6 @@ void LLParticipantList::sort()  	if ( !mAvatarList )  		return; -	// TODO: Implement more sorting orders after specs updating (EM)  	switch ( mSortOrder ) {  	case E_SORT_BY_NAME :  		// if mExcludeAgent == true , then no need to keep agent on top of the list @@ -326,17 +321,25 @@ void LLParticipantList::sort()  			mAvatarList->sort();  		}  		break; +	case E_SORT_BY_RECENT_SPEAKERS: +		if (mSortByRecentSpeakers.isNull()) +			mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this); +		mAvatarList->setComparator(mSortByRecentSpeakers.get()); +		mAvatarList->sort(); +		break;  	default :  		llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl;  		return;  	}  } -void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id) +void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)  {  	if (mExcludeAgent && gAgent.getID() == avatar_id) return; +	if (mAvatarList->contains(avatar_id)) return; -	existing_list.push_back(avatar_id); +	mAvatarList->getIDs().push_back(avatar_id); +	mAvatarList->setDirty();  	adjustParticipant(avatar_id);  } @@ -356,7 +359,7 @@ bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::L  {  	/**  	 * We need to filter speaking objects. These objects shouldn't appear in the list -	 * @c LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy +	 * @see LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy  	 */  	const LLUUID& speaker_id = event->getValue().asUUID();  	LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id); @@ -402,6 +405,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;  	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +	registrar.add("ParticipantList.Sort", boost::bind(&LLParticipantList::LLParticipantListMenu::sortParticipantList, this, _2));  	registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2));  	registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2)); @@ -447,6 +451,24 @@ void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const  		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false);  		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false);  	} + +	// Don't show sort options for P2P chat +	bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1); +	LLMenuGL::sMenuContainer->childSetVisible("SortByName", is_sort_visible); +	LLMenuGL::sMenuContainer->childSetVisible("SortByRecentSpeakers", is_sort_visible); +} + +void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata) +{ +	std::string param = userdata.asString(); +	if ("sort_by_name" == param) +	{ +		mParent.setSortOrder(E_SORT_BY_NAME); +	} +	else if ("sort_by_recent_speakers" == param) +	{ +		mParent.setSortOrder(E_SORT_BY_RECENT_SPEAKERS); +	}  }  void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata) @@ -555,37 +577,50 @@ void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(co  bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata)  {  	std::string item = userdata.asString(); -	if (item == "can_mute_text") +	if (item == "can_mute_text" || "can_block" == item)  	{  		return mUUIDs.front() != gAgentID;  	} -	else -		if (item == "can_allow_text_chat" || "can_moderate_voice" == item) +	else if (item == "can_allow_text_chat") +	{ +		return isGroupModerator(); +	} +	else if ("can_moderate_voice" == item) +	{ +		if (isGroupModerator())  		{ -			return isGroupModerator(); +			LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(mUUIDs.front()); +			if (speakerp.notNull()) +			{ +				// not in voice participants can not be moderated +				return speakerp->mStatus == LLSpeaker::STATUS_VOICE_ACTIVE +					|| speakerp->mStatus == LLSpeaker::STATUS_MUTED; +			}  		} +		return false; +	}  	else if (item == std::string("can_add")) -		{ -			// We can add friends if: -			// - there are selected people -			// - and there are no friends among selection yet. +	{ +		// We can add friends if: +		// - there are selected people +		// - and there are no friends among selection yet. -			bool result = (mUUIDs.size() > 0); +		bool result = (mUUIDs.size() > 0); -			std::vector<LLUUID>::const_iterator -				id = mUUIDs.begin(), -				uuids_end = mUUIDs.end(); +		std::vector<LLUUID>::const_iterator +			id = mUUIDs.begin(), +			uuids_end = mUUIDs.end(); -			for (;id != uuids_end; ++id) +		for (;id != uuids_end; ++id) +		{ +			if ( LLAvatarActions::isFriend(*id) )  			{ -				if ( LLAvatarActions::isFriend(*id) ) -				{ -					result = false; -					break; -				} +				result = false; +				break;  			} -			return result;  		} +		return result; +	}  	else if (item == "can_call")  	{  		return LLVoiceClient::voiceEnabled(); @@ -616,8 +651,45 @@ bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD&  	{  		return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat);  	} +	else if(item == "is_sorted_by_name") +	{ +		return E_SORT_BY_NAME == mParent.mSortOrder; +	} +	else if(item == "is_sorted_by_recent_speakers") +	{ +		return E_SORT_BY_RECENT_SPEAKERS == mParent.mSortOrder; +	}  	return false;  } +bool LLParticipantList::LLAvatarItemRecentSpeakerComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const +{ +	if (mParent.mSpeakerMgr) +	{ +		LLPointer<LLSpeaker> lhs = mParent.mSpeakerMgr->findSpeaker(avatar_item1->getAvatarId()); +		LLPointer<LLSpeaker> rhs = mParent.mSpeakerMgr->findSpeaker(avatar_item2->getAvatarId()); +		if ( lhs.notNull() && rhs.notNull() ) +		{ +			// Compare by last speaking time +			if( lhs->mLastSpokeTime != rhs->mLastSpokeTime ) +				return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime ); +			else if ( lhs->mSortIndex != rhs->mSortIndex ) +				return ( lhs->mSortIndex < rhs->mSortIndex ); +		} +		else if ( lhs.notNull() ) +		{ +			// True if only avatar_item1 speaker info available +			return true; +		} +		else if ( rhs.notNull() ) +		{ +			// False if only avatar_item2 speaker info available +			return false; +		} +	} +	// By default compare by name. +	return LLAvatarItemNameComparator::doCompare(avatar_item1, avatar_item2); +} +  //EOF diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 72c413d188..d15ec980db 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -34,6 +34,7 @@  #include "llevent.h"  #include "llpanelpeoplemenus.h"  #include "llimview.h" +#include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator  class LLSpeakerMgr;  class LLAvatarList; @@ -43,24 +44,44 @@ class LLParticipantList  {  	LOG_CLASS(LLParticipantList);  	public: -		LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true); + +		typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t; + +		LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true);  		~LLParticipantList();  		void setSpeakingIndicatorsVisible(BOOL visible);  		typedef enum e_participant_sort_oder {  			E_SORT_BY_NAME = 0, +			E_SORT_BY_RECENT_SPEAKERS = 1,  		} EParticipantSortOrder;  		/** +		 * Adds specified avatar ID to the existing list if it is not Agent's ID +		 * +		 * @param[in] avatar_id - Avatar UUID to be added into the list +		 */ +		void addAvatarIDExceptAgent(const LLUUID& avatar_id); + +		/**  		 * Set and sort Avatarlist by given order  		 */  		void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); +		EParticipantSortOrder getSortOrder(); + +		/** +		 * Refreshes the participant list if it's in sort by recent speaker order. +		 */ +		void updateRecentSpeakersOrder();  		/** -		 * Refreshes participants to display ones not in voice as disabled. -		 * TODO: mantipov: probably should be moved into derived class for LLFloaterCall +		 * Set a callback to be called before adding a speaker. Invalid speakers will not be added. +		 * +		 * If the callback is unset all speakers are considered as valid. +		 * +		 * @see onAddItemEvent()  		 */ -		void refreshVoiceState(); +		void setValidateSpeakerCallback(validate_speaker_callback_t cb);  	protected:  		/** @@ -139,6 +160,7 @@ class LLParticipantList  			bool enableContextMenuItem(const LLSD& userdata);  			bool checkContextMenuItem(const LLSD& userdata); +			void sortParticipantList(const LLSD& userdata);  			void toggleAllowTextChat(const LLSD& userdata);  			void toggleMute(const LLSD& userdata, U32 flags);  			void toggleMuteText(const LLSD& userdata); @@ -195,19 +217,26 @@ class LLParticipantList  			void moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute);  		}; +		/** +		 * Comparator for comparing avatar items by last spoken time +		 */ +		class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount +		{ +			LOG_CLASS(LLAvatarItemRecentSpeakerComparator); +		  public: +			LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){}; +			virtual ~LLAvatarItemRecentSpeakerComparator() {}; +		  protected: +			virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const; +		  private: +			LLParticipantList& mParent; +		}; +  	private:  		void onAvatarListDoubleClicked(LLAvatarList* list);  		void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);  		/** -		 * Adds specified avatar ID to the existing list if it is not Agent's ID -		 * -		 * @param[in, out] existing_list - vector with avatars' UUIDs already in the list -		 * @param[in] avatar_id - Avatar UUID to be added into the list -		 */ -		void addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id); - -		/**  		 * Adjusts passed participant to work properly.  		 *  		 * Adds SpeakerMuteListener to process moderation actions. @@ -240,4 +269,7 @@ class LLParticipantList  		boost::signals2::connection mAvatarListDoubleClickConnection;  		boost::signals2::connection mAvatarListRefreshConnection;  		boost::signals2::connection mAvatarListReturnConnection; + +		LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers; +		validate_speaker_callback_t mValidateSpeakerCallback;  }; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp new file mode 100644 index 0000000000..4de953a59d --- /dev/null +++ b/indra/newview/llplacesinventorypanel.cpp @@ -0,0 +1,191 @@ +/**  + * @file llplacesinventorypanel.cpp + * @brief LLPlacesInventoryPanel  class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + *  + * Copyright (c) 2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llscrollcontainer.h" + +#include "llplacesinventorypanel.h" + +#include "llfoldervieweventlistener.h" +#include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llpanellandmarks.h" +#include "llplacesinventorybridge.h" + +static LLDefaultChildRegistry::Register<LLPlacesInventoryPanel> r("places_inventory_panel"); + +static const LLPlacesInventoryBridgeBuilder PLACES_INVENTORY_BUILDER; + +LLPlacesInventoryPanel::LLPlacesInventoryPanel(const Params& p) :  +	LLInventoryPanel(p), +	mSavedFolderState(NULL) + +{ +	mInvFVBridgeBuilder = &PLACES_INVENTORY_BUILDER; +	mSavedFolderState = new LLSaveFolderState(); +	mSavedFolderState->setApply(FALSE); +} + + +LLPlacesInventoryPanel::~LLPlacesInventoryPanel() +{ +	delete mSavedFolderState; +} + +BOOL LLPlacesInventoryPanel::postBuild() +{ +	LLInventoryPanel::postBuild(); + +	// clear Contents(); +	{ +		mFolders->destroyView(); +		mFolders->getParent()->removeChild(mFolders); +		mFolders->die(); + +		if( mScroller ) +		{ +			removeChild( mScroller ); +			mScroller->die(); +			mScroller = NULL; +		} +		mFolders = NULL; +	} + + +	mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves + +	// create root folder +	{ +		LLRect folder_rect(0, +			0, +			getRect().getWidth(), +			0); +		LLPlacesFolderView::Params p; +		p.name = getName(); +		p.rect = folder_rect; +		p.parent_panel = this; +		mFolders = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p); +		mFolders->setAllowMultiSelect(mAllowMultiSelect); +	} + +	mCommitCallbackRegistrar.popScope(); + +	mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); + +	// scroller +	{ +		LLRect scroller_view_rect = getRect(); +		scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); +		LLScrollContainer::Params p; +		p.name("Inventory Scroller"); +		p.rect(scroller_view_rect); +		p.follows.flags(FOLLOWS_ALL); +		p.reserve_scroll_corner(true); +		p.tab_stop(true); +		mScroller = LLUICtrlFactory::create<LLScrollContainer>(p); +	} +	addChild(mScroller); +	mScroller->addChild(mFolders); + +	mFolders->setScrollContainer(mScroller); + + +	// cut subitems +	mFolders->setUseEllipses(true); + +	return TRUE; +} + +// save current folder open state +void LLPlacesInventoryPanel::saveFolderState() +{ +	mSavedFolderState->setApply(FALSE); +	getRootFolder()->applyFunctorRecursively(*mSavedFolderState); +} + +// re-open folders which state was saved +void LLPlacesInventoryPanel::restoreFolderState() +{ +	mSavedFolderState->setApply(TRUE); +	getRootFolder()->applyFunctorRecursively(*mSavedFolderState); +	LLOpenFoldersWithSelection opener; +	getRootFolder()->applyFunctorRecursively(opener); +	getRootFolder()->scrollToShowSelection(); +} + +/************************************************************************/ +/* PROTECTED METHODS                                                    */ +/************************************************************************/ + + + +/************************************************************************/ +/*              LLPlacesFolderView implementation                       */ +/************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +//  PUBLIC METHODS +////////////////////////////////////////////////////////////////////////// + +BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ +	// let children to change selection first +	childrenHandleRightMouseDown(x, y, mask); +	mParentLandmarksPanel->setCurrentSelectedList((LLPlacesInventoryPanel*)getParentPanel()); + +	// then determine its type and set necessary menu handle +	if (getCurSelectedItem()) +	{ +		LLInventoryType::EType inventory_type = getCurSelectedItem()->getListener()->getInventoryType(); +		inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type); + +		if (it_handle != mMenuHandlesByInventoryType.end()) +		{ +			mPopupMenuHandle = (*it_handle).second; +		} +		else +		{ +			llwarns << "Requested menu handle for non-setup inventory type: " << inventory_type << llendl; +		} + +	} + +	return LLFolderView::handleRightMouseDown(x, y, mask); +} + +void LLPlacesFolderView::setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle) +{ +	mMenuHandlesByInventoryType[asset_type] = menu_handle; +} + +// EOF diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h new file mode 100644 index 0000000000..7b34045d32 --- /dev/null +++ b/indra/newview/llplacesinventorypanel.h @@ -0,0 +1,96 @@ +/**  + * @file llplacesinventorypanel.h + * @brief LLPlacesInventoryPanel class declaration + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + *  + * Copyright (c) 2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYSUBTREEPANEL_H +#define LL_LLINVENTORYSUBTREEPANEL_H + +#include "llfloaterinventory.h" +#include "llinventorypanel.h" +#include "llfolderview.h" + +class LLLandmarksPanel; + +class LLPlacesInventoryPanel : public LLInventoryPanel +{ +public: +	struct Params  +		:	public LLInitParam::Block<Params, LLInventoryPanel::Params> +	{ +		Params() +		{} +	}; + +	LLPlacesInventoryPanel(const Params& p); +	~LLPlacesInventoryPanel(); + +	/*virtual*/ BOOL postBuild(); + +	void saveFolderState(); +	void restoreFolderState(); + +private: +	LLSaveFolderState*			mSavedFolderState; +}; + + +class LLPlacesFolderView : public LLFolderView +{ +public: +	LLPlacesFolderView(const LLFolderView::Params& p) : LLFolderView(p) {}; +	/** +	 *	Handles right mouse down +	 * +	 * Contains workaround for EXT-2786: sets current selected list for landmark +	 * panel using @c mParentLandmarksPanel which is set in @c LLLandmarksPanel::initLandmarksPanel +	 */ +	/*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + +	void setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle); + +	void setParentLandmarksPanel(LLLandmarksPanel* panel) +	{ +		mParentLandmarksPanel = panel; +	} + +	S32 getSelectedCount() { return (S32)mSelectedItems.size(); } + +private: +	/** +	 * holds pointer to landmark panel. This pointer is used in @c LLPlacesFolderView::handleRightMouseDown +	 */ +	LLLandmarksPanel* mParentLandmarksPanel; +	typedef std::map<LLInventoryType::EType, LLHandle<LLView> > inventory_type_menu_handle_t; +	inventory_type_menu_handle_t mMenuHandlesByInventoryType; + +}; + +#endif //LL_LLINVENTORYSUBTREEPANEL_H diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 5f6b210767..7a48f890e0 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -72,10 +72,12 @@ const S32 ANIMATION_FRAMES = 1; //13;  LLProgressView::LLProgressView(const LLRect &rect)   :	LLPanel(),  	mPercentDone( 0.f ), -	mMouseDownInActiveArea( false ) +	mMouseDownInActiveArea( false ), +	mUpdateEvents("LLProgressView")  {  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_progress.xml");  	reshape(rect.getWidth(), rect.getHeight()); +	mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1));  }  BOOL LLProgressView::postBuild() @@ -260,3 +262,26 @@ void LLProgressView::onClickMessage(void* data)  		}  	}  } + +bool LLProgressView::handleUpdate(const LLSD& event_data) +{ +	LLSD message = event_data.get("message"); +	LLSD desc = event_data.get("desc"); +	LLSD percent = event_data.get("percent"); + +	if(message.isDefined()) +	{ +		setMessage(message.asString()); +	} + +	if(desc.isDefined()) +	{ +		setText(desc.asString()); +	} +	 +	if(percent.isDefined()) +	{ +		setPercent(percent.asReal()); +	} +	return false; +} diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h index 865646c85d..6853674d88 100644 --- a/indra/newview/llprogressview.h +++ b/indra/newview/llprogressview.h @@ -35,6 +35,7 @@  #include "llpanel.h"  #include "llframetimer.h" +#include "llevents.h"  class LLImageRaw;  class LLButton; @@ -75,7 +76,12 @@ protected:  	LLRect mOutlineRect;  	bool mMouseDownInActiveArea; +	// The LLEventStream mUpdateEvents depends upon this class being a singleton +	// to avoid pump name conflicts.  	static LLProgressView* sInstance; +	LLEventStream mUpdateEvents;  + +	bool handleUpdate(const LLSD& event_data);  };  #endif // LL_LLPROGRESSVIEW_H diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index bd256ec9c2..8c3f3dc5fb 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -217,7 +217,10 @@ void LLScreenChannel::addToast(const LLToast::Params& p)  	ToastElem new_toast_elem(p); +	// reset HIDDEN flags for the Overflow Toast  	mOverflowToastHidden = false; +	if(mOverflowToastPanel) +		mOverflowToastPanel->setIsHidden(false);  	new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1));  	new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1)); @@ -459,7 +462,7 @@ void LLScreenChannel::showToastsBottom()  	S32		toast_margin = 0;  	std::vector<ToastElem>::reverse_iterator it; -	closeOverflowToastPanel(); +	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());  	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)  	{ @@ -473,6 +476,16 @@ void LLScreenChannel::showToastsBottom()  		toast_rect.setOriginAndSize(getRect().mLeft, bottom + toast_margin, toast_rect.getWidth() ,toast_rect.getHeight());  		(*it).toast->setRect(toast_rect); +		// don't show toasts if there is not enough space +		if(floater && floater->overlapsScreenChannel()) +		{ +			LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); +			if(toast_rect.mTop + getOverflowToastHeight() + toast_margin > world_rect.mTop) +			{ +				break; +			} +		} +  		bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop;  		if(!stop_showing_toasts) @@ -513,7 +526,11 @@ void LLScreenChannel::showToastsBottom()  			mHiddenToastsNum++;  		}  		createOverflowToast(bottom, gSavedSettings.getS32("NotificationTipToastLifeTime")); -	}	 +	} +	else +	{ +		closeOverflowToastPanel(); +	}  }  //-------------------------------------------------------------------------- @@ -544,11 +561,14 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)  	LLRect toast_rect;  	LLToast::Params p;  	p.lifetime_secs = timer; -	mOverflowToastPanel = new LLToast(p); + +	if(!mOverflowToastPanel) +		mOverflowToastPanel = new LLToast(p);  	if(!mOverflowToastPanel)  		return; +	mOverflowToastPanel->startFading();  	mOverflowToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onOverflowToastHide, this));  	LLTextBox* text_box = mOverflowToastPanel->getChild<LLTextBox>("toast_text"); @@ -567,6 +587,18 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)  	toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight());	  	mOverflowToastPanel->setRect(toast_rect); +	// don't show overflow toast if there is not enough space for it. +	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); +	if(floater && floater->overlapsScreenChannel()) +	{ +		LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); +		if(toast_rect.mTop > world_rect.mTop) +		{ +			closeOverflowToastPanel(); +			return; +		} +	} +  	text_box->setValue(text);  	text_box->setVisible(TRUE); @@ -606,8 +638,8 @@ void LLScreenChannel::closeOverflowToastPanel()  {  	if(mOverflowToastPanel != NULL)  	{ -		mOverflowToastPanel->closeFloater(); -		mOverflowToastPanel = NULL; +		mOverflowToastPanel->setVisible(FALSE); +		mOverflowToastPanel->stopFading();  	}  } @@ -656,6 +688,24 @@ F32 LLScreenChannel::getHeightRatio()  	return ratio;  } +S32 LLScreenChannel::getOverflowToastHeight() +{ +	if(mOverflowToastPanel) +	{ +		return mOverflowToastPanel->getRect().getHeight(); +	} + +	static S32 height = 0; +	if(0 == height) +	{ +		LLToast::Params p; +		LLToast* toast = new LLToast(p); +		height = toast->getRect().getHeight(); +		delete toast; +	} +	return height; +} +  //--------------------------------------------------------------------------  void LLScreenChannel::updateStartUpString(S32 num)  { @@ -814,25 +864,22 @@ void LLScreenChannel::updateShowToastsState()  		return;  	} -	// for Message Well floater showed in a docked state - adjust channel's height -	if(dynamic_cast<LLSysWellWindow*>(floater) || dynamic_cast<LLIMFloater*>(floater) -		|| dynamic_cast<LLScriptFloater*>(floater)) +	S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");; +	LLRect this_rect = getRect(); + +	// adjust channel's height +	if(floater->overlapsScreenChannel())  	{ -		S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");; -		LLRect this_rect = getRect(); -		if(floater->getVisible() && floater->isDocked()) +		channel_bottom += floater->getRect().getHeight(); +		if(floater->getDockControl())  		{ -			channel_bottom += floater->getRect().getHeight(); -			if(floater->getDockControl()) -			{ -				channel_bottom += floater->getDockControl()->getTongueHeight(); -			} +			channel_bottom += floater->getDockControl()->getTongueHeight();  		} +	} -		if(channel_bottom != this_rect.mBottom) -		{ -			setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom)); -		} +	if(channel_bottom != this_rect.mBottom) +	{ +		setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom));  	}  } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 321fb244a1..38f27f756b 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -281,6 +281,8 @@ private:  	 */  	static F32 getHeightRatio(); +	S32 getOverflowToastHeight(); +  	// Channel's flags  	static bool	mWasStartUpToastShown; diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 1962d871a6..cf62d47362 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -67,6 +67,7 @@ LLScriptFloater::LLScriptFloater(const LLSD& key)  , mScriptForm(NULL)  {  	setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this)); +	setOverlapsScreenChannel(true);  }  bool LLScriptFloater::toggle(const LLUUID& object_id) diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp index fd39bde118..8f2c877c7a 100644 --- a/indra/newview/llspeakbutton.cpp +++ b/indra/newview/llspeakbutton.cpp @@ -61,7 +61,9 @@ void LLSpeakButton::draw()  {  	// gVoiceClient is the authoritative global source of info regarding our open-mic state, we merely reflect that state.  	bool openmic = gVoiceClient->getUserPTTState(); -	mSpeakBtn->setToggleState(openmic); +	bool voiceenabled = gVoiceClient->voiceEnabled(); +	mSpeakBtn->setToggleState(openmic && voiceenabled); +	mOutputMonitor->setIsMuted(!voiceenabled);  	LLUICtrl::draw();  } @@ -121,7 +123,7 @@ LLSpeakButton::LLSpeakButton(const Params& p)  	mOutputMonitor->setIsAgentControl(true);  	//*TODO find a better place to do that -	LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1)); +	LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true);  }  LLSpeakButton::~LLSpeakButton() diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 3861a96355..010dfd1b33 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -615,6 +615,9 @@ private:  void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)  { +	LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id); +	if (!speakerp) return; +  	std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");  	LLSD data;  	data["method"] = "mute update"; @@ -623,15 +626,13 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)  	data["params"]["agent_id"] = speaker_id;  	data["params"]["mute_info"] = LLSD::emptyMap();  	//current value represents ability to type, so invert -	data["params"]["mute_info"]["text"] = !findSpeaker(speaker_id)->mModeratorMutedText; +	data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText;  	LLHTTPClient::post(url, data, new ModerationResponder(getSessionID()));  }  void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute)  { -	if (gAgentID == avatar_id) return; // do not process myself -  	LLPointer<LLSpeaker> speakerp = findSpeaker(avatar_id);  	if (!speakerp) return; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 73e7d99815..eb2275bff0 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1082,6 +1082,17 @@ bool idle_startup()  		credentials["passwd"] = gPassword;  		login->connect(credentials); +		LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK ); +		return FALSE; +	} + +	if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState()) +	{ +		// If we get here we have gotten past the potential stall +		// in curl, so take "may appear frozen" out of progress bar. JC +		auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); +		set_startup_status(progress, auth_desc, auth_message); +  		LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );  		return FALSE;  	} @@ -1168,16 +1179,6 @@ bool idle_startup()  				show_connect_box = true;  			}  		} -		else -		{ -			// Still waiting for response. -			// *TODO:Mani - Actually check for login progress. -			// If we get here we have gotten past the potential stall -			// in curl, so take "may appear frozen" out of progress bar. JC -			auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); -			set_startup_status(progress, auth_desc, auth_message); -		} -  		return FALSE;  	} @@ -2703,6 +2704,7 @@ std::string LLStartUp::startupStateToString(EStartupState state)  		RTNENUM( STATE_LOGIN_WAIT );  		RTNENUM( STATE_LOGIN_CLEANUP );  		RTNENUM( STATE_LOGIN_AUTH_INIT ); +		RTNENUM( STATE_LOGIN_CURL_UNSTUCK );  		RTNENUM( STATE_LOGIN_PROCESS_RESPONSE );  		RTNENUM( STATE_WORLD_INIT );  		RTNENUM( STATE_MULTIMEDIA_INIT ); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index ab11b42e74..92fe9521d3 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -55,6 +55,7 @@ typedef enum {  	STATE_LOGIN_WAIT,				// Wait for user input at login screen  	STATE_LOGIN_CLEANUP,			// Get rid of login screen and start login  	STATE_LOGIN_AUTH_INIT,			// Start login to SL servers +	STATE_LOGIN_CURL_UNSTUCK,		// Update progress to remove "SL appears frozen" msg.  	STATE_LOGIN_PROCESS_RESPONSE,	// Check authentication reply  	STATE_WORLD_INIT,				// Start building the world  	STATE_MULTIMEDIA_INIT,			// Init the rest of multimedia library diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 9e72464237..23c4f00ab7 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -160,6 +160,7 @@ LLStatusBar::LLStatusBar(const LLRect& rect)  	mBtnVolume = getChild<LLButton>( "volume_btn" );  	mBtnVolume->setClickedCallback( onClickVolume, this );  	mBtnVolume->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterVolume, this)); +	mBtnVolume->setIsChrome(TRUE);  	gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2)); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 26f9824f9c..bcaefc3690 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -63,6 +63,7 @@ LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key)  {  	mTypedItemsCount[IT_NOTIFICATION] = 0;  	mTypedItemsCount[IT_INSTANT_MESSAGE] = 0; +	setOverlapsScreenChannel(true);  }  //--------------------------------------------------------------------------------- @@ -352,6 +353,7 @@ LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID&  	}  	// Initialize chiclet. +	mChiclet->setRect(LLRect(5, 28, 30, 3)); // *HACK: workaround for (EXT-3599)  	mChiclet->setChicletSizeChangedCallback(boost::bind(&LLIMWellWindow::RowPanel::onChicletSizeChanged, this, mChiclet, _2));  	mChiclet->enableCounterControl(true);  	mChiclet->setCounter(chicletCounter); @@ -742,12 +744,13 @@ BOOL LLIMWellWindow::postBuild()  void LLIMWellWindow::sessionAdded(const LLUUID& session_id,  								   const std::string& name, const LLUUID& other_participant_id)  { -	if (mMessageList->getItemByValue(session_id)) return; +	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); +	if (!session) return; -	// For im sessions started as voice call chiclet gets created on the first incoming message -	if (gIMMgr->isVoiceCall(session_id)) return; +	// no need to spawn chiclets for participants in P2P calls called through Avaline +	if (session->isP2P() && session->isOtherParticipantAvaline()) return; -	if (!gIMMgr->hasSession(session_id)) return; +	if (mMessageList->getItemByValue(session_id)) return;  	addIMRow(session_id, 0, name, other_participant_id);	  	reshapeWindow(); @@ -905,23 +908,6 @@ bool LLIMWellWindow::hasIMRow(const LLUUID& session_id)  	return mMessageList->getItemByValue(session_id);  } -void LLIMWellWindow::onNewIM(const LLSD& data) -{ -	LLUUID from_id = data["from_id"]; -	if (from_id.isNull() || gAgentID == from_id) return; - -	LLUUID session_id = data["session_id"]; -	if (session_id.isNull()) return; - -	if (!gIMMgr->isVoiceCall(session_id)) return; - -	if (hasIMRow(session_id)) return; - -	//first real message, time to create chiclet -	addIMRow(session_id); -} - -  void LLIMWellWindow::closeAll()  {  	// Generate an ignorable alert dialog if there is an active voice IM sesion diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 6cfa25b84d..7030f4b427 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -191,8 +191,6 @@ public:  	/*virtual*/ void sessionRemoved(const LLUUID& session_id);  	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); -	void onNewIM(const LLSD& data); -  	void addObjectRow(const LLUUID& object_id, bool new_message = false);  	void removeObjectRow(const LLUUID& object_id); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 5f7c2f5080..25e5e23e6f 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1237,6 +1237,7 @@ void LLTextureCtrl::draw()  	// Using the discard level, do not show the string if the texture is almost but not   	// fully loaded.  	if ( mTexturep.notNull() && +		 (!mTexturep->isFullyLoaded()) &&  		 (mShowLoadingPlaceholder == TRUE) &&   		 (mTexturep->getDiscardLevel() != 1) &&  		 (mTexturep->getDiscardLevel() != 0)) diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 0b232da62b..fb1d591e32 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -45,7 +45,7 @@  class LLButton;  class LLFloaterTexturePicker;  class LLInventoryItem; -class LLViewerTexture; +class LLViewerFetchedTexture;  // used for setting drag & drop callbacks.  typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback; @@ -189,7 +189,7 @@ private:  	drag_n_drop_callback	 mDropCallback;  	commit_callback_t		 mOnCancelCallback;  	commit_callback_t		 mOnSelectCallback; -	LLPointer<LLViewerTexture> mTexturep; +	LLPointer<LLViewerFetchedTexture> mTexturep;  	LLUIColor				 mBorderColor;  	LLUUID					 mImageItemID;  	LLUUID					 mImageAssetID; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index e80dafe245..a75f631769 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -801,7 +801,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == SEND_HTTP_REQ)  	{  		{ -			const S32 HTTP_QUEUE_MAX_SIZE = 32; +			const S32 HTTP_QUEUE_MAX_SIZE = 8;  			// *TODO: Integrate this with llviewerthrottle  			// Note: LLViewerThrottle uses dynamic throttling which makes sense for UDP,  			// but probably not for Textures. @@ -842,10 +842,10 @@ bool LLTextureFetchWorker::doWork(S32 param)  				mLoaded = FALSE;  				mGetStatus = 0;  				mGetReason.clear(); -				lldebugs << "HTTP GET: " << mID << " Offset: " << offset -						<< " Bytes: " << mRequestedSize -						<< " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth -						<< llendl; +				LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << offset +									 << " Bytes: " << mRequestedSize +									 << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth +									 << LL_ENDL;  				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);  				mState = WAIT_HTTP_REQ;	 @@ -874,12 +874,30 @@ bool LLTextureFetchWorker::doWork(S32 param)  			S32 cur_size = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;  			if (mRequestedSize < 0)  			{ -				const S32 HTTP_MAX_RETRY_COUNT = 3; -				S32 max_attempts = (mGetStatus == HTTP_NOT_FOUND) ? 1 : HTTP_MAX_RETRY_COUNT + 1; - 				llinfos << "HTTP GET failed for: " << mUrl -						<< " Status: " << mGetStatus << " Reason: '" << mGetReason << "'" -						<< " Attempt:" << mHTTPFailCount+1 << "/" << max_attempts << llendl; -				++mHTTPFailCount; +				S32 max_attempts; +				if (mGetStatus == HTTP_NOT_FOUND) +				{ +					mHTTPFailCount = max_attempts = 1; // Don't retry +					llinfos << "Texture missing from server (404): " << mUrl << llendl; +				} +				else if (mGetStatus == HTTP_SERVICE_UNAVAILABLE) +				{ +					// *TODO: Should probably introduce a timer here to delay future HTTP requsts +					// for a short time (~1s) to ease server load? Ideally the server would queue +					// requests instead of returning 503... we already limit the number pending. +					++mHTTPFailCount; +					max_attempts = mHTTPFailCount+1; // Keep retrying +					LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL; +				} +				else +				{ +					const S32 HTTP_MAX_RETRY_COUNT = 3; +					max_attempts = HTTP_MAX_RETRY_COUNT + 1; +					++mHTTPFailCount; +					llinfos << "HTTP GET failed for: " << mUrl +							<< " Status: " << mGetStatus << " Reason: '" << mGetReason << "'" +							<< " Attempt:" << mHTTPFailCount+1 << "/" << max_attempts << llendl; +				}  				if (mHTTPFailCount >= max_attempts)  				{  					if (cur_size > 0) @@ -1239,7 +1257,7 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,  		gTextureList.sTextureBits += data_size * 8; // Approximate - does not include header bits -		//llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl; +		LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL;  		if (data_size > 0)  		{  			// *TODO: set the formatted image data here directly to avoid the copy @@ -1432,8 +1450,9 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con  	if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))  	{  		// Only do partial requests for J2C at the moment -		//llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl;  +		//llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl;  		desired_size = MAX_IMAGE_DATA_SIZE; +		desired_discard = 0;  	}  	else if (desired_discard == 0)  	{ diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index c48301fa1e..c3ccb9380b 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -279,7 +279,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  			mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight());  			mLineEditor->setRect(leditor_rect);  			mLineEditor->setText(edit_text_contents); -			mLineEditor->setMaxTextLength(STD_STRING_STR_LEN); +			mLineEditor->setMaxTextLength(STD_STRING_STR_LEN - 1);  			// make sure all edit keys get handled properly (DEV-22396)  			mLineEditor->setHandleEditKeysDirectly(TRUE); @@ -385,6 +385,12 @@ BOOL LLToastAlertPanel::handleKeyHere(KEY key, MASK mask )  {  	if( KEY_RETURN == key && mask == MASK_NONE )  	{ +		LLButton* defaultBtn = getDefaultButton(); +		if(defaultBtn && defaultBtn->getVisible() && defaultBtn->getEnabled()) +		{ +			// If we have a default button, click it when return is pressed +			defaultBtn->onCommit(); +		}  		return TRUE;  	}  	else if (KEY_RIGHT == key) diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index b7add03e0e..d62017cc2f 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -35,13 +35,14 @@  #include "llnotifications.h"  #include "llinstantmessage.h" +#include "llviewerchat.h"  const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT	= 6;  //--------------------------------------------------------------------------  LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notification), -															mAvatar(NULL), mUserName(NULL), -															mTime(NULL), mMessage(NULL) +								mAvatar(NULL), mUserName(NULL), +								mTime(NULL), mMessage(NULL)  {  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_instant_message.xml"); @@ -52,8 +53,11 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  	mMessage = getChild<LLTextBox>("message");  	LLStyle::Params style_params; -	style_params.font.name(LLFontGL::nameFromFont(style_params.font)); -	style_params.font.size(LLFontGL::sizeFromFont(style_params.font)); +	LLFontGL* fontp = LLViewerChat::getChatFont(); +	std::string font_name = LLFontGL::nameFromFont(fontp); +	std::string font_size = LLFontGL::sizeFromFont(fontp); +	style_params.font.name(font_name); +	style_params.font.size(font_size);  	style_params.font.style = "UNDERLINE";  	//Handle IRC styled /me messages. @@ -63,13 +67,16 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  		mMessage->clear();  		style_params.font.style ="ITALIC"; -		mMessage->appendText(p.from + " ", FALSE, style_params); +		mMessage->appendText(p.from, FALSE, style_params);  		style_params.font.style = "ITALIC";  		mMessage->appendText(p.message.substr(3), FALSE, style_params);  	}  	else +	{  		mMessage->setValue(p.message); +	} +  	mUserName->setValue(p.from);  	mTime->setValue(p.time);  	mSessionID = p.session_id; diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 74fbce890d..b1d09eccba 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -731,14 +731,13 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)  				// *HACK: We may select this object, so pretend it was clicked  				mPick = mHoverPick;  				LLInspector::Params p; +				p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());  				p.message(avatar_name);  				p.image(LLUI::getUIImage("Info"));  				p.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));  				p.visible_time_near(6.f);  				p.visible_time_far(3.f);  				p.wrap(false); - -				p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());  				LLToolTipMgr::instance().show(p);  			} @@ -822,6 +821,7 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)  					// We may select this object, so pretend it was clicked  					mPick = mHoverPick;  					LLInspector::Params p; +					p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());  					p.message(tooltip_msg);  					p.image(LLUI::getUIImage("Info_Off"));  					p.click_callback(boost::bind(showObjectInspector, hover_object->getID(), mHoverPick.mObjectFace)); @@ -833,8 +833,6 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)  					p.visible_time_near(6.f);  					p.visible_time_far(3.f);  					p.wrap(false); - -					p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());  					LLToolTipMgr::instance().show(p);  				} diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp index 7befb87248..347399f239 100644 --- a/indra/newview/lltransientfloatermgr.cpp +++ b/indra/newview/lltransientfloatermgr.cpp @@ -37,6 +37,7 @@  #include "llrootview.h"  #include "llviewerwindow.h"  #include "lldockablefloater.h" +#include "llmenugl.h"  LLTransientFloaterMgr::LLTransientFloaterMgr() @@ -87,6 +88,13 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,  	for (controls_set_t::iterator it = mControlsSet.begin(); it  			!= mControlsSet.end(); it++)  	{ +		// don't hide transient floater if any context menu opened +		if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL) +		{ +			hide = false; +			break; +		} +  		LLView* control_view = *it;  		if (!control_view->getVisible())  		{ diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index df62c9628d..bf96472e7e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -166,11 +166,18 @@ public:  		// 2xx status codes indicate success.  		// Most 4xx status codes are successful enough for our purposes.  		// 499 is the error code for host not found, timeout, etc. +		// 500 means "Internal Server error" but we decided it's okay to  +		//     accept this and go past it in the MIME type probe +		// 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com +		// 499 is a code specifc to join.secondlife.com (????) apparently safe to ignore  		if(	((status >= 200) && (status < 300))	|| -			((status >= 400) && (status < 499))	) +			((status >= 400) && (status < 499))	||  +			(status == 500) || +			(status == 302) || +			(status == 499)  +			)  		{  			// The probe was successful. -			  			if(mime_type.empty())  			{  				// Some sites don't return any content-type header at all. diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp index 90cfb85821..e9293ac5a4 100644 --- a/indra/newview/llviewermedia_streamingaudio.cpp +++ b/indra/newview/llviewermedia_streamingaudio.cpp @@ -1,7 +1,7 @@  /**    * @file llviewermedia_streamingaudio.h   * @author Tofu Linden, Sam Kolb - * @brief LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugins API. + * @brief LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugin API.   *   * $LicenseInfo:firstyear=2009&license=viewergpl$   *  @@ -33,6 +33,7 @@  #include "llviewerprecompiledheaders.h"  #include "linden_common.h"  #include "llpluginclassmedia.h" +#include "llpluginclassmediaowner.h"  #include "llviewermedia.h"  #include "llviewermedia_streamingaudio.h" @@ -61,18 +62,18 @@ void LLStreamingAudio_MediaPlugins::start(const std::string& url)  	if (!mMediaPlugin) // lazy-init the underlying media plugin  	{  		mMediaPlugin = initializeMedia("audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis. -		llinfos << "mMediaPlugin is now " << mMediaPlugin << llendl; +		llinfos << "steaming audio mMediaPlugin is now " << mMediaPlugin << llendl;  	}  	if(!mMediaPlugin)  		return; -	 +  	if (!url.empty()) {  		llinfos << "Starting internet stream: " << url << llendl;  		mURL = url;  		mMediaPlugin->loadURI ( url );  		mMediaPlugin->start(); -		llinfos << "Playing....." << llendl;		 +		llinfos << "Playing stream..." << llendl;		  	} else {  		llinfos << "setting stream to NULL"<< llendl;  		mURL.clear(); @@ -82,6 +83,7 @@ void LLStreamingAudio_MediaPlugins::start(const std::string& url)  void LLStreamingAudio_MediaPlugins::stop()  { +	llinfos << "Stopping internet stream." << llendl;  	if(mMediaPlugin)  	{  		mMediaPlugin->stop(); @@ -97,10 +99,12 @@ void LLStreamingAudio_MediaPlugins::pause(int pause)  	if(pause)  	{ +		llinfos << "Pausing internet stream." << llendl;  		mMediaPlugin->pause();  	}   	else   	{ +		llinfos << "Unpausing internet stream." << llendl;  		mMediaPlugin->start();  	}  } @@ -114,20 +118,21 @@ void LLStreamingAudio_MediaPlugins::update()  int LLStreamingAudio_MediaPlugins::isPlaying()  {  	if (!mMediaPlugin) -		return 0; +		return 0; // stopped -	// *TODO: can probably do better than this -	if (mMediaPlugin->isPluginRunning()) -	{ -		return 1; // Active and playing -	}	 +	LLPluginClassMediaOwner::EMediaStatus status = +		mMediaPlugin->getStatus(); -	if (mMediaPlugin->isPluginExited()) +	switch (status)  	{ +	case LLPluginClassMediaOwner::MEDIA_LOADING: // but not MEDIA_LOADED +	case LLPluginClassMediaOwner::MEDIA_PLAYING: +		return 1; // Active and playing +	case LLPluginClassMediaOwner::MEDIA_PAUSED: +		return 2; // paused +	default:  		return 0; // stopped  	} - -	return 2; // paused  }  void LLStreamingAudio_MediaPlugins::setGain(F32 vol) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 23bcca9603..2a9c738c97 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6479,21 +6479,27 @@ void menu_toggle_attached_particles(void* user_data)  	LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");  } -class LLAdvancedHandleAttchedLightParticles: public view_listener_t +class LLAdvancedHandleAttachedLightParticles: public view_listener_t  {  	bool handleEvent(const LLSD& userdata)  	{  		std::string control_name = userdata.asString(); + +		// toggle the control +		gSavedSettings.setBOOL(control_name, +				       !gSavedSettings.getBOOL(control_name)); + +		// update internal flags  		if (control_name == "RenderAttachedLights") -{ +		{  			menu_toggle_attached_lights(NULL); -} +		}  		else if (control_name == "RenderAttachedParticles") -{ +		{  			menu_toggle_attached_particles(NULL); -} +		}  		return true; -} +	}  };  class LLSomethingSelected : public view_listener_t @@ -7423,12 +7429,17 @@ class LLEditTakeOff : public view_listener_t  	{  		std::string clothing = userdata.asString();  		if (clothing == "all") -			LLAgentWearables::userRemoveAllClothes(); +			LLWearableBridge::removeAllClothesFromAvatar();  		else  		{  			EWearableType type = LLWearableDictionary::typeNameToType(clothing);  			if (type >= WT_SHAPE && type < WT_COUNT) -				LLAgentWearables::userRemoveWearable(type); +			{ +				// MULTI-WEARABLES +				LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>(gAgentWearables.getWearableInventoryItem(type,0)); +				LLWearableBridge::removeItemFromAvatar(item); +			} +				  		}  		return true;  	} @@ -7758,7 +7769,7 @@ void initialize_menus()  	view_listener_t::addMenu(new LLAdvancedVectorizePerfTest(), "Advanced.VectorizePerfTest");  	view_listener_t::addMenu(new LLAdvancedToggleFrameTest(), "Advanced.ToggleFrameTest");  	view_listener_t::addMenu(new LLAdvancedCheckFrameTest(), "Advanced.CheckFrameTest"); -	view_listener_t::addMenu(new LLAdvancedHandleAttchedLightParticles(), "Advanced.HandleAttchedLightParticles"); +	view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles");  	#ifdef TOGGLE_HACKED_GODLIKE_VIEWER diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 6a31bbfa1e..87045d2abf 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -906,6 +906,18 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f  				  LLFloaterReg::showInstance("preview_texture", LLSD(item_id), take_focus);  				  break;  			  } +			  case LLAssetType::AT_ANIMATION: +				  LLFloaterReg::showInstance("preview_anim", LLSD(item_id), take_focus); +				  break; +			  case LLAssetType::AT_GESTURE: +				  LLFloaterReg::showInstance("preview_gesture", LLSD(item_id), take_focus); +				  break; +			  case LLAssetType::AT_SCRIPT: +				  LLFloaterReg::showInstance("preview_script", LLSD(item_id), take_focus); +				  break; +			  case LLAssetType::AT_SOUND: +				  LLFloaterReg::showInstance("preview_sound", LLSD(item_id), take_focus); +				  break;  			  default:  				break;  			} @@ -1146,9 +1158,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  		default:  			LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;  			break; -		}	// end switch (mIM) -			 -		// Show falls through to accept. +		} +		break; +		// end switch (mIM)  	case IOR_ACCEPT:  		msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1)); @@ -1837,7 +1849,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			// This is a block, modeless dialog.  			//*TODO: Translate  			args["MESSAGE"] = message; -			LLNotificationsUtil::add("SystemMessage", args); +			LLNotificationsUtil::add("SystemMessageTip", args);  		}  		break;  	case IM_GROUP_NOTICE: @@ -2514,14 +2526,9 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)  		std::string prefix = mesg.substr(0, 4);  		if (prefix == "/me " || prefix == "/me'")  		{ -//			chat.mText = from_name; -//			chat.mText += mesg.substr(3);  			ircstyle = TRUE;  		} -//		else -//		{ -			chat.mText = mesg; -//		} +		chat.mText = mesg;  		// Look for the start of typing so we can put "..." in the bubbles.  		if (CHAT_TYPE_START == chat.mChatType) diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 69d2458217..993853b9a6 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -446,6 +446,17 @@ void LLVoiceChannel::resume()  	}  } +boost::signals2::connection LLVoiceChannel::setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front) +{ +	if (at_front) +	{ +		return sCurrentVoiceChannelChangedSignal.connect(cb,  boost::signals2::at_front); +	} +	else +	{ +		return sCurrentVoiceChannelChangedSignal.connect(cb); +	} +}  //  // LLVoiceChannelGroup diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 77801142cb..cb86671305 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -64,7 +64,7 @@ public:  	typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t;  	typedef boost::signals2::signal<void(const LLUUID& session_id)> channel_changed_signal_t;  	static channel_changed_signal_t sCurrentVoiceChannelChangedSignal; -	static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb) { return sCurrentVoiceChannelChangedSignal.connect(cb); } +	static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front = false);  	LLVoiceChannel(const LLUUID& session_id, const std::string& session_name); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index cfa1f05ec0..c2d26a1971 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -4443,6 +4443,33 @@ void LLVoiceClient::participantUpdatedEvent(  				participant->mPower = 0.0f;  			}  			participant->mVolume = volume; + +			 +			// *HACH: mantipov: added while working on EXT-3544 +			/* +			Sometimes LLVoiceClient::participantUpdatedEvent callback is called BEFORE  +			LLViewerChatterBoxSessionAgentListUpdates::post() sometimes AFTER. +			 +			participantUpdatedEvent updates voice participant state in particular participantState::mIsModeratorMuted +			Originally we wanted to update session Speaker Manager to fire LLSpeakerVoiceModerationEvent to fix the EXT-3544 bug. +			Calling of the LLSpeakerMgr::update() method was added into LLIMMgr::processAgentListUpdates. +			 +			But in case participantUpdatedEvent() is called after LLViewerChatterBoxSessionAgentListUpdates::post() +			voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager +			and event is not fired. + +			So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it +			in LLCallFloater::draw() +			*/ +			LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel(); +			if (voice_cnl) +			{ +				LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(voice_cnl->getSessionID()); +				if (speaker_manager) +				{ +					speaker_manager->update(true); +				} +			}  		}  		else  		{ diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index f98aa361e0..70bfc67523 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -134,9 +134,21 @@ public:  	virtual F64 getMediaInterest() const   		{  -			F64 tmp = mObject->getTotalMediaInterest();   -			return (tmp < 0.0) ? mObject->getPixelArea() : tmp;  +			F64 interest = mObject->getTotalMediaInterest(); +			if (interest < (F64)0.0) +			{ +				// media interest not valid yet, try pixel area +				interest = mObject->getPixelArea(); +				// HACK: force recalculation of pixel area if interest is the "magic default" of 1024. +				if (interest == 1024.f) +				{ +					const_cast<LLVOVolume*>(static_cast<LLVOVolume*>(mObject))->setPixelAreaAndAngle(gAgent); +					interest = mObject->getPixelArea(); +				} +			} +			return interest;   		} +	  	virtual bool isInterestingEnough() const  		{  			return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest()); diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index f8bb7336db..7866f735c5 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -38,10 +38,12 @@  // Library includes  #include "llwindow.h"	// spawnWebBrowser() +#include "llagent.h"  #include "llappviewer.h"  #include "llfloatermediabrowser.h"  #include "llfloaterreg.h"  #include "lllogininstance.h" +#include "llparcel.h"  #include "llsd.h"  #include "lltoastalertpanel.h"  #include "llui.h" @@ -49,6 +51,8 @@  #include "llversioninfo.h"  #include "llviewercontrol.h"  #include "llviewernetwork.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h"  #include "llviewerwindow.h"  class URLLoader : public LLToastAlertPanel::URLLoader @@ -144,7 +148,27 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url,  	substitution["LANGUAGE"] = LLUI::getLanguage();  	substitution["GRID"] = LLViewerLogin::getInstance()->getGridLabel();  	substitution["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple(); +	substitution["SESSION_ID"] = gAgent.getSessionID(); +	// find the region ID +	LLUUID region_id; +	LLViewerRegion *region = gAgent.getRegion(); +	if (region) +	{ +		region_id = region->getRegionID(); +	} +	substitution["REGION_ID"] = region_id; + +	// find the parcel ID +	LLUUID parcel_id; +	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +	if (parcel) +	{ +		parcel_id = parcel->getID(); +	} +	substitution["PARCEL_ID"] = parcel_id; + +	// expand all of the substitution strings and escape the url  	std::string expanded_url = url;  	LLStringUtil::format(expanded_url, substitution); diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index e6857ea780..1940d65ae4 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -334,7 +334,6 @@ void LLWorldMapView::draw()  	gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);  	gGL.setColorMask(true, true); -#if 1  	// Draw the image tiles  	drawMipmap(width, height);  	gGL.flush(); @@ -452,7 +451,7 @@ void LLWorldMapView::draw()  		// Draw the region name in the lower left corner  		if (sMapScale >= DRAW_TEXT_THRESHOLD)  		{ -			LLFontGL* font = LLFontGL::getFontSansSerifSmall(); +			LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Small", LLFontGL::BOLD));  			std::string mesg;  			if (info->isDown())  			{ @@ -468,14 +467,13 @@ void LLWorldMapView::draw()  					mesg, 0,  					llfloor(left + 3), llfloor(bottom + 2),  					LLColor4::white, -					LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); +					LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW);  			}  		}  	} -	#endif -	#if 1 +  	// Draw background rectangle  	LLGLSUIDefault gls_ui;  	{ @@ -566,7 +564,7 @@ void LLWorldMapView::draw()  			drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, getString("Loading"), "");  		}  	} -	#endif +  	// turn off the scissor  	LLGLDisable no_scissor(GL_SCISSOR_TEST); diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp index 9897f40c4e..1cdccd2baa 100644 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -186,9 +186,8 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32  LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level)  {  	// Get the grid coordinates -//	std::string imageurl = llformat("http://map.secondlife.com.s3.amazonaws.com/%d/%05d/%05d/map-%d-%d-%d-objects.jpg",  	std::string imageurl = llformat("http://map.secondlife.com.s3.amazonaws.com/map-%d-%d-%d-objects.jpg", -									level, grid_x, grid_y, level, grid_x, grid_y); +									level, grid_x, grid_y);  	// DO NOT COMMIT!! DEBUG ONLY!!!  	// Use a local jpeg for every tile to test map speed without S3 access diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 73b5222ee3..4f4fc83819 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6352,7 +6352,8 @@ void LLPipeline::renderDeferredLighting()  			mDeferredLight[0].flush(); -			if (gSavedSettings.getBOOL("RenderDeferredBlurLight")) +			if (gSavedSettings.getBOOL("RenderDeferredBlurLight") && +			    gSavedSettings.getBOOL("RenderDeferredGI"))  			{  				LLFastTimer ftm(FTM_EDGE_DETECTION);  				//get edge map diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 88e77f11ee..cb511c2f0b 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -71,10 +71,14 @@  	<color  	 name="Transparent"  	 value="0 0 0 0" /> +  <!-- Make potentially unused colors show up bright purple. +  Leave this here until all Unused? are removed below, otherwise +  the viewer generates many warnings on startup. --> +  <color +	 name="Unused?" +	 value="1 0 1 1" /> - - -	<!-- UI Definitions --> +  <!-- UI Definitions -->  	<color       name="AgentChatColor" @@ -98,6 +102,24 @@       name="AvatarNameColor"       reference="White" />      <color +     name="AvatarListItemIconDefaultColor" +     reference="White" /> +    <color +     name="AvatarListItemIconOnlineColor" +     reference="White" /> +    <color +     name="AvatarListItemIconOfflineColor" +     value="0.5 0.5 0.5 0.5" /> +    <color +     name="AvatarListItemIconVoiceInvitedColor" +     reference="AvatarListItemIconOfflineColor" /> +    <color +     name="AvatarListItemIconVoiceJoinedColor" +     reference="AvatarListItemIconOnlineColor" /> +    <color +     name="AvatarListItemIconVoiceLeftColor" +     reference="AvatarListItemIconOfflineColor" /> +    <color       name="BackgroundChatColor"       reference="DkGray_66" />      <color diff --git a/indra/newview/skins/default/textures/icons/SL_Logo.png b/indra/newview/skins/default/textures/icons/SL_Logo.pngBinary files differ new file mode 100644 index 0000000000..c9fbde987a --- /dev/null +++ b/indra/newview/skins/default/textures/icons/SL_Logo.png diff --git a/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpgBinary files differ new file mode 100644 index 0000000000..3bb7f7183c --- /dev/null +++ b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 412f8b6d68..95db84cb32 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -70,6 +70,8 @@ with the same filename but different name    <texture name="Audio_Over" file_name="icons/Audio_Over.png" preload="false" />    <texture name="Audio_Press" file_name="icons/Audio_Press.png" preload="false" /> +  <texture name="Avaline_Icon" file_name="icons/avaline_default_icon.jpg" preload="true" /> +      <texture name="BackArrow_Disabled" file_name="icons/BackArrow_Disabled.png" preload="false" />    <texture name="BackArrow_Off" file_name="icons/BackArrow_Off.png" preload="false" />    <texture name="BackArrow_Press" file_name="icons/BackArrow_Press.png" preload="false" /> @@ -234,6 +236,7 @@ with the same filename but different name    <texture name="Inv_Gloves" file_name="icons/Inv_Gloves.png" preload="false" />    <texture name="Inv_Hair" file_name="icons/Inv_Hair.png" preload="false" />    <texture name="Inv_LinkItem" file_name="icons/Inv_LinkItem.png" preload="false" /> +  <texture name="Inv_LinkItem_Broken" file_name="icons/Inv_LinkItem_Broken.png" preload="false" />    <texture name="Inv_LinkFolder" file_name="icons/Inv_LinkFolder.png" preload="false" />    <texture name="Inv_Jacket" file_name="icons/Inv_Jacket.png" preload="false" />    <texture name="Inv_LookFolderOpen" file_name="icons/Inv_LookFolderOpen.png" preload="false" /> @@ -487,7 +490,8 @@ with the same filename but different name    <texture name="SliderThumb_Off" file_name="widgets/SliderThumb_Off.png" />    <texture name="SliderThumb_Disabled" file_name="widgets/SliderThumb_Disabled.png" />    <texture name="SliderThumb_Press" file_name="widgets/SliderThumb_Press.png" /> -  <texture name="SL_Logo" file_name="map_infohub.tga" /> + +  <texture name="SL_Logo" file_name="icons/SL_Logo.png" preload="true" />    <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />    <texture name="Snapshot_Over" file_name="bottomtray/Snapshot_Over.png" preload="false" /> @@ -495,12 +499,12 @@ with the same filename but different name    <texture name="startup_logo"  file_name="windows/startup_logo.png" preload="true" /> -  <texture name="Stepper_Down_Disabled" file_name="widgets/Stepper_Down_Disabled.png" preload="true" /> -  <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="true" /> -  <texture name="Stepper_Down_Press" file_name="widgets/Stepper_Down_Press.png" preload="true" /> -  <texture name="Stepper_Up_Disabled" file_name="widgets/Stepper_Up_Disabled.png" preload="true" /> -  <texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="true" /> -  <texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="true" /> +  <texture name="Stepper_Down_Disabled" file_name="widgets/Stepper_Down_Disabled.png" preload="false" /> +  <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="false" /> +  <texture name="Stepper_Down_Press" file_name="widgets/Stepper_Down_Press.png" preload="false" /> +  <texture name="Stepper_Up_Disabled" file_name="widgets/Stepper_Up_Disabled.png" preload="false" /> +  <texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="false" /> +  <texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="false" />    <texture name="Stop_Off" file_name="icons/Stop_Off.png" preload="false" />    <texture name="Stop_Over" file_name="icons/Stop_Over.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 6956b73371..cb4cbd229a 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -15,21 +15,21 @@   title="TEST FLOATER"   save_dock_state="true"   save_visibility="true" - single_instance="true" + single_instance="true"    width="320">    <string name="nudge_parabuild">Nudge 1</string>    <string name="test_the_vlt">This string is extracted.</string>    <chat_history     allow_html="true"     bg_readonly_color="ChatHistoryBgColor" -   bg_writeable_color="ChatHistoryBgColor" -   border_visible="false"  +   bg_writeable_color="ChatHistoryBgColor"  +   border_visible="false"     follows="all"     font="SansSerif"  -	    left="1" +	 left="1"     top="20"     layout="topleft" -	    height="260" +	 height="260"     name="chat_history"     parse_highlights="true"     text_color="ChatHistoryTextColor" diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index a581190d18..cc955369e2 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -4,6 +4,7 @@   height="420"   layout="topleft"   name="floaterland" + help_topic="floaterland"   save_rect="true"   title="ABOUT LAND"   width="490"> diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml index ffdb59d44c..94686f0bb0 100644 --- a/indra/newview/skins/default/xui/en/floater_customize.xml +++ b/indra/newview/skins/default/xui/en/floater_customize.xml @@ -55,6 +55,7 @@           label="Shape"           layout="topleft"           name="Shape" +         help_topic="customize_shape_tab"           width="400">              <icon               follows="top|right" @@ -340,6 +341,7 @@ scratch and wear it.           label="Skin"           layout="topleft"           name="Skin" +         help_topic="customize_skin_tab"           width="400">              <icon               follows="top|right" @@ -591,6 +593,7 @@ scratch and wear it.           label="Hair"           layout="topleft"           name="Hair" +         help_topic="customize_hair_tab"           width="400">              <icon               follows="top|right" @@ -812,6 +815,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Eyes" +         help_topic="customize_eyes_tab"           top_delta="0"           width="389">              <icon @@ -1010,6 +1014,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Shirt" +         help_topic="customize_shirt_tab"           top_delta="0"           width="389">              <icon @@ -1215,6 +1220,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Pants" +         help_topic="customize_pants_tab"           top_delta="0"           width="389">              <icon @@ -1420,6 +1426,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Shoes" +         help_topic="customize_shoes_tab"           top_delta="0"           width="389">              <icon @@ -1625,6 +1632,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Socks" +         help_topic="customize_socks_tab"           top_delta="0"           width="389">              <icon @@ -1830,6 +1838,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Jacket" +         help_topic="customize_jacket_tab"           top_delta="0"           width="389">              <icon @@ -2047,6 +2056,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Gloves" +         help_topic="customize_gloves_tab"           top_delta="0"           width="389">              <icon @@ -2252,6 +2262,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Undershirt" +         help_topic="customize_undershirt_tab"           top_delta="0"           width="389">              <icon @@ -2457,6 +2468,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Underpants" +         help_topic="customize_underpants_tab"           top_delta="0"           width="389">              <icon @@ -2662,6 +2674,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Skirt" +         help_topic="customize_skirt_tab"           top_delta="0"           width="389">              <icon @@ -2867,6 +2880,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Alpha" +         help_topic="customize_alpha_tab"           top_delta="0"           width="389">              <icon @@ -3154,6 +3168,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Tattoo" +         help_topic="customize_tattoo_tab"           top_delta="0"           width="389">              <icon diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml index 81c54ae55e..b9ce11600f 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -11,6 +11,10 @@   title="UNKNOWN PERSON IS CALLING"   width="410">      <floater.string +     name="lifetime"> +        5 +    </floater.string> +    <floater.string       name="localchat">          Nearby Voice Chat      </floater.string> diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml index fb8893678d..920f0c909a 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -16,8 +16,10 @@   can_dock="true"   bevel_style="in"   height="300" + min_width="150"   layout="topleft"   name="nearby_chat" + help_topic="nearby_chat"   save_rect="true"   title="NEARBY CHAT"   save_dock_state="true" diff --git a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml index c6bc093c6c..104ac2143f 100644 --- a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml +++ b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml @@ -11,6 +11,10 @@   title="CALLING"   width="410">      <floater.string +     name="lifetime"> +        5 +    </floater.string> +    <floater.string       name="localchat">          Nearby Voice Chat      </floater.string> diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml index 2f26e5d0c1..15655a920e 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences.xml @@ -7,6 +7,7 @@   height="460"   layout="topleft"   name="Preferences" + help_topic="preferences"   single_instance="true"   title="PREFERENCES"   width="620"> diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml index 9c1a5499db..5a9e2ebe6e 100644 --- a/indra/newview/skins/default/xui/en/floater_search.xml +++ b/indra/newview/skins/default/xui/en/floater_search.xml @@ -4,8 +4,8 @@   can_resize="true"   height="646"   layout="topleft" - min_height="140" - min_width="467" + min_height="646" + min_width="670"   name="floater_search"   help_topic="floater_search"   save_rect="true" diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index ec54522d3e..a36a1b591b 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -9,6 +9,7 @@   name="Snapshot"   help_topic="snapshot"   save_rect="true" + save_visibility="true"   title="SNAPSHOT PREVIEW"   width="215">      <floater.string diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml index 7f31692ad9..32739ac953 100644 --- a/indra/newview/skins/default/xui/en/floater_water.xml +++ b/indra/newview/skins/default/xui/en/floater_water.xml @@ -4,6 +4,7 @@   height="240"   layout="topleft"   name="Water Floater" + help_topic="water_floater"   save_rect="true"   title="ADVANCED WATER EDITOR"   width="700"> diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index e632b67d11..8904d4f49c 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -296,7 +296,7 @@       layout="topleft"       name="pg_label"       width="60"> -        PG +        General      </text>      <check_box @@ -330,7 +330,7 @@       layout="topleft"       name="mature_label"       width="66"> -        Mature +        Moderate      </text>      <check_box @@ -361,7 +361,7 @@       top_delta="2"       left_pad="3"       layout="topleft" -     name="pg_label" +     name="adult_label"       width="66">          Adult      </text> @@ -480,7 +480,10 @@       name="location"       select_on_focus="true"       tool_tip="Type the name of a region" -     width="152" /> +     width="152"> +               <search_editor.commit_callback +                function="WMap.Location" /> +  </search_editor>     <button       follows="top|right"       height="23" diff --git a/indra/newview/skins/default/xui/en/menu_participant_list.xml b/indra/newview/skins/default/xui/en/menu_participant_list.xml index faf33bd1b1..31263fbea8 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml @@ -2,7 +2,29 @@  <context_menu   layout="topleft"   name="Participant List Context Menu"> - <menu_item_call +    <menu_item_check +     label="Sort by Name" +     layout="topleft" +     name="SortByName"> +        <menu_item_check.on_click +         function="ParticipantList.Sort" +         parameter="sort_by_name" /> +        <menu_item_check.on_check +         function="ParticipantList.CheckItem" +         parameter="is_sorted_by_name" /> +    </menu_item_check> +    <menu_item_check +     label="Sort by Recent Speakers" +     layout="topleft" +     name="SortByRecentSpeakers"> +        <menu_item_check.on_click +         function="ParticipantList.Sort" +         parameter="sort_by_recent_speakers" /> +        <menu_item_check.on_check +         function="ParticipantList.CheckItem" +         parameter="is_sorted_by_recent_speakers" /> +    </menu_item_check> +    <menu_item_call       label="View Profile"       layout="topleft"       name="View Profile"> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups.xml b/indra/newview/skins/default/xui/en/menu_people_groups.xml new file mode 100644 index 0000000000..afa680139d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_groups.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false"> +  <menu_item_call +   label="View Info" +   name="View Info"> +    <menu_item_call.on_click +     function="People.Groups.Action" +     parameter="view_info" /> +    <menu_item_call.on_enable +     function="People.Groups.Enable" +     parameter="view_info" /> +  </menu_item_call> +  <menu_item_call +   label="Chat" +   name="Chat"> +    <menu_item_call.on_click +     function="People.Groups.Action" +     parameter="chat" /> +    <menu_item_call.on_enable +     function="People.Groups.Enable" +     parameter="chat" /> +  </menu_item_call> +  <menu_item_call +   label="Call" +   name="Call"> +    <menu_item_call.on_click +     function="People.Groups.Action" +     parameter="call" /> +    <menu_item_call.on_enable +     function="People.Groups.Enable" +     parameter="call" /> +  </menu_item_call> +  <menu_item_separator /> +  <menu_item_call +   label="Activate" +   name="Activate"> +    <menu_item_call.on_click +     function="People.Groups.Action" +     parameter="activate" /> +    <menu_item_call.on_enable +     function="People.Groups.Enable" +     parameter="activate" /> +  </menu_item_call> +  <menu_item_separator /> +  <menu_item_call +   label="Leave" +   name="Leave"> +    <menu_item_call.on_click +     function="People.Groups.Action" +     parameter="leave" /> +    <menu_item_call.on_enable +     function="People.Groups.Enable" +     parameter="leave" /> +  </menu_item_call> +</menu> diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml index c849188699..9b3948b29b 100644 --- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml +++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml @@ -104,6 +104,9 @@          <on_click           function="Places.LandmarksGear.Folding.Action"           parameter="expand_all" /> +        <on_enable +         function="Places.LandmarksGear.Enable" +         parameter="expand_all" />      </menu_item_call>      <menu_item_call       label="Collapse all folders" @@ -112,6 +115,9 @@          <on_click           function="Places.LandmarksGear.Folding.Action"           parameter="collapse_all" /> +        <on_enable +         function="Places.LandmarksGear.Enable" +         parameter="collapse_all" />      </menu_item_call>      <menu_item_check       label="Sort by Date" diff --git a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml index d0128d1c9a..1dc1c610cf 100644 --- a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml +++ b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml @@ -19,4 +19,40 @@          <menu_item_call.on_click           function="Profile.Share" />      </menu_item_call> +  <menu_item_call +   label="Kick" +   layout="topleft" +   name="kick"> +    <menu_item_call.on_click +     function="Profile.Kick" /> +    <menu_item_call.on_visible +     function="Profile.EnableGod" /> +  </menu_item_call> +  <menu_item_call +   label="Freeze" +   layout="topleft" +   name="freeze"> +    <menu_item_call.on_click +     function="Profile.Freeze" /> +    <menu_item_call.on_visible +     function="Profile.EnableGod" /> +  </menu_item_call> +  <menu_item_call +   label="Unfreeze" +   layout="topleft" +   name="unfreeze"> +    <menu_item_call.on_click +     function="Profile.Unfreeze" /> +    <menu_item_call.on_visible +     function="Profile.EnableGod" /> +  </menu_item_call> +  <menu_item_call +   label="CSR" +   layout="topleft" +   name="csr"> +    <menu_item_call.on_click +     function="Profile.CSR" /> +    <menu_item_call.on_visible +     function="Profile.EnableGod" /> +  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b4ce32ea1d..0640ae21de 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2481,30 +2481,30 @@               name="Debug Pipeline">                  <menu_item_check.on_check                   function="CheckControl" -                 parameter="RenderDebugGL" /> +                 parameter="RenderDebugPipeline" />                  <menu_item_check.on_click                   function="ToggleControl" -                 parameter="RenderDebugGL" /> +                 parameter="RenderDebugPipeline" />              </menu_item_check>              <menu_item_check               label="Fast Alpha"               name="Fast Alpha">                  <menu_item_check.on_check                   function="CheckControl" -                 parameter="RenderDebugGL" /> +                 parameter="RenderFastAlpha" />                  <menu_item_check.on_click                   function="ToggleControl" -                 parameter="RenderDebugGL" /> +                 parameter="RenderFastAlpha" />              </menu_item_check>              <menu_item_check               label="Animation Textures"               name="Animation Textures">                  <menu_item_check.on_check                   function="CheckControl" -                 parameter="RenderDebugGL" /> +                 parameter="AnimateTextures" />                  <menu_item_check.on_click                   function="ToggleControl" -                 parameter="RenderDebugGL" /> +                 parameter="AnimateTextures" />              </menu_item_check>              <menu_item_check               label="Disable Textures" @@ -2555,7 +2555,7 @@                   function="CheckControl"                   parameter="RenderAttachedLights" />                  <menu_item_check.on_click -                 function="Advanced.HandleAttchedLightParticles" +                 function="Advanced.HandleAttachedLightParticles"                   parameter="RenderAttachedLights" />              </menu_item_check>              <menu_item_check @@ -2565,7 +2565,7 @@                   function="CheckControl"                   parameter="RenderAttachedParticles" />                  <menu_item_check.on_click -                 function="Advanced.HandleAttchedLightParticles" +                 function="Advanced.HandleAttachedLightParticles"                   parameter="RenderAttachedParticles" />              </menu_item_check>              <menu_item_check @@ -2975,14 +2975,6 @@              <menu_item_call.on_click               function="Advanced.SendTestIMs" />            </menu_item_call> -          <menu_item_call -           label="Test Inspectors" -           name="Test Inspectors" -           shortcut="control|shift|I"> -            <menu_item_call.on_click -             function="Floater.Show" -             parameter="test_inspectors" /> -          </menu_item_call>          </menu>          <menu           create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d4b712e048..9d3c31c4e6 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4498,14 +4498,14 @@ You don't have permission to copy this.    <notification     icon="notifytip.tga"     name="InventoryAccepted" -   type="offer"> +   type="notifytip">  [NAME] received your inventory offer.    </notification>    <notification     icon="notifytip.tga"     name="InventoryDeclined" -   type="offer"> +   type="notifytip">  [NAME] declined your inventory offer.    </notification> @@ -5022,9 +5022,9 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O  [ITEM_SLURL]      <form name="form">        <button -       index="0" -       name="Keep" -       text="Keep"/> +       index="4" +       name="Show" +       text="Show"/>        <button         index="1"         name="Discard" @@ -5106,7 +5106,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O    <notification     icon="notify.tga"     name="OfferFriendship" -   type="offer"> +   type="alertmodal">  [NAME] is offering friendship.  [MESSAGE] diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 3e2910458f..00eba94f47 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -227,16 +227,20 @@              <button  			 follows="left|right"               height="23" +             image_selected="PushButton_Selected_Press" +             image_pressed="PushButton_Press" +             image_pressed_selected="PushButton_Selected_Press"               left="0"               label=""               layout="topleft"               name="snapshots"               width="36"               top="4" +             is_toggle="true"               image_overlay="Snapshot_Off"               tool_tip="Take snapshot"> -				<button.commit_callback -				 function="Floater.Toggle" +				<button.init_callback +				 function="Button.SetFloaterToggle"  				 parameter="snapshot" />  			</button>  		</layout_panel> @@ -248,7 +252,7 @@           top="0"           name="chiclet_list_panel"           width="189" -         min_width="180" +         min_width="100"           user_resize="false"           auto_resize="true">  <!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same @@ -259,7 +263,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.               height="23"               layout="topleft"               left="1" -             min_width="180" +             min_width="110"               name="chiclet_list"               top="6"               chiclet_padding="4" @@ -327,6 +331,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.           min_width="35"           user_resize="false">              <chiclet_im_well +             max_displayed_count="99"               flash_period="0.3"               follows="right"               height="23" @@ -356,7 +361,6 @@ image_pressed_selected  "Lit" + "Selected" - there are new messages and the Well                   image_selected="PushButton_Selected_Press"                   label_color="Black"                   left="0" -                 max_displayed_count="99"                   name="Unread IM messages"                   pad_left="0"                   pad_right="0" diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml index 859822dd81..39c4923f12 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_header.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml @@ -28,7 +28,7 @@        height="12"        layout="topleft"        left_pad="5" -      right="-60" +      right="-120"        name="user_name"        text_color="white"        bg_readonly_color="black" @@ -46,5 +46,5 @@       right="-5"       top="8"           value="23:30" -         width="50" /> +         width="110" />  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml index b5760e977f..1fbf7abda9 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml @@ -103,6 +103,7 @@           top_pad="2"           max_length="63"           name="classified_name" +         prevalidate_callback="ascii"           text_color="black"           width="290" />          <text diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index 9f06e64560..744ee43f57 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -228,6 +228,16 @@                   top_pad="10"                   value="Title:"                   width="290" /> +                <text +                 follows="left|top" +                 height="22" +                 layout="topleft" +                 left="0" +                 name="title_value" +                 text_color="white" +                 top_pad="5" +                 use_ellipses="true" +                 width="290" />                   <line_editor                   background_image_disabled="task_panel_background.png"                   follows="left|top|right" @@ -238,7 +248,7 @@                   name="title_editor"                   prevalidate_callback="ascii"                   text_readonly_color="white" -                 top_pad="5" +                 top_delta="0"                   width="290" />                  <text                   follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 1f211c0fed..c899dcb750 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -23,7 +23,7 @@           layout="topleft"           name="tab_favorites"           title="Favorites bar"> -            <inventory_subtree_panel +            <places_inventory_panel               allow_multi_select="true"               border="true"               bottom="0" @@ -39,7 +39,7 @@           layout="topleft"           name="tab_landmarks"           title="Landmarks"> -            <inventory_subtree_panel +            <places_inventory_panel               allow_multi_select="true"               border="true"               bottom="0" @@ -55,7 +55,7 @@           layout="topleft"           name="tab_inventory"           title="My Inventory"> -            <inventory_subtree_panel +            <places_inventory_panel               allow_multi_select="true"               border="true"               bottom="0" @@ -71,7 +71,7 @@             layout="topleft"             name="tab_library"             title="Library"> -            <inventory_subtree_panel +            <places_inventory_panel               allow_multi_select="true"               border="true"               bottom="0" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index 5c99022f35..d6d8e9562b 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -3,7 +3,7 @@   <panel name="Outfits"   background_visible="true"    follows="all" - height="550" + height="570"   label="Things"   layout="topleft"   min_height="350" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 8883c27c47..08a10553a8 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -411,5 +411,15 @@ background_visible="true"           name="chat_btn"           tool_tip="Open chat session"           width="110" /> +        <button +         follows="bottom|left" +         top="4" +         left_pad="2" +         height="23" +         label="Group Call" +         layout="topleft" +         name="group_call_btn" +         tool_tip="Call this group" +         width="110" />      </panel>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index b14089c3a2..97790535d0 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -263,10 +263,12 @@  		  width="38"  		  right="-2"  		  top="-1" +     	mouse_opaque="false"  		  orientation="horizontal">  		<layout_panel  			layout="topleft"  			width="16" +     	mouse_opaque="false"  			auto_resize="false"  			user_resize="false">  		  <icon @@ -282,6 +284,7 @@  		<layout_panel  			layout="topleft"  			width="16" +     	mouse_opaque="false"  			auto_resize="false"  			user_resize="false">  		  <icon diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index 57b090e5b4..3578c4326d 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -80,16 +80,6 @@       name="volume_btn"       tool_tip="Global Volume Control"       width="16" /> -    <panel -     class="panel_volume_pulldown" -     follows="all" -     height="533" -     layout="topleft" -     left="0" -     name="volume_pulldown" -     top="5" -     visible="false" -     width="313" />      <text       enabled="true" diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index 7f4b4aef82..44248eedd5 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -2,23 +2,24 @@  <panel  background_visible="true"  follows="all" -height="635" +height="570"  label="Outfits"  layout="topleft" -min_height="460" +min_height="350" +min_width="240"  name="appearance panel"  top="0"  left="0" -   width="333"> +width="333">     <string     name="No Outfit"     value="No Outfit" />     <panel     left="0"     top="0" -   follows="left|top|right" +   follows="all"     layout="topleft" -   width="333" +   width="330"     height="33"     name="panel_currentlook"     > @@ -85,9 +86,9 @@ left="0"     class="panel_outfits_inventory"     filename="panel_outfits_inventory.xml"     name="panel_outfits_inventory" -   height="550" -   min_height="510" -   width="333" +   height="515" +   min_height="410" +   width="320"     top_pad="0"     follows="all"     /> diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml index 7b0b4b0bde..790f8afd3a 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -33,10 +33,10 @@       	 height="18"       	 image_name="Lock"  	     layout="topleft" -		 right="-50" +		 right="-15"  	     mouse_opaque="true"  	     name="IconLocked" -	     top="4" +	     top="8"  	     width="18" />      <button       follows="top|right" @@ -60,14 +60,23 @@       use_ellipses="true"       value="Object Profile"       width="275" /> +    	    <text +     follows="top|left" +     height="13" +     layout="topleft" +     left="45" +     name="where" +     text_color="LtGray_50" +     value="(Inventory)" +     width="150" />  	<panel           follows="all" -         height="500" +         height="490"           label=""           layout="topleft"           left="10"           help_topic="" -         top="30" +         top="45"           width="313"     background_visible="true"     bg_alpha_color="DkGray2"> @@ -125,7 +134,7 @@  		     layout="topleft"      		 left="5"  		     name="LabelCreatorTitle" -top_pad="10" +		  top_pad="10"  		     width="78">  	        Creator:      	</text> @@ -135,7 +144,7 @@ top_pad="10"       default_icon_name="Generic_Person"       layout="topleft"       left_pad="0" -		     top_delta="-6" +     top_delta="-6"       mouse_opaque="true"       width="20" />  	    <text @@ -165,28 +174,28 @@ top_pad="10"  			 follows="left|top"  			 height="23"  			 layout="topleft" -    		 left="5" +			   left="5"  			 name="LabelOwnerTitle" -top_pad="5" +			   top_pad="10"  			 width="78">  			    Owner:  	     </text>  	     <avatar_icon -     follows="top|left" -     height="20" -     default_icon_name="Generic_Person" -     layout="topleft" -     left_pad="0" -		     top_delta="-6" -     mouse_opaque="true" -     width="20" /> +			   follows="top|left" +			   height="20" +			   default_icon_name="Generic_Person" +			   layout="topleft" +			   left_pad="0" +			   top_delta="-6" +			   mouse_opaque="true" +			   width="20" />  	     <text  			 type="string" -     follows="left|right" -     font="SansSerifSmall" -     height="15" -     layout="topleft" -     left_pad="5" +			   follows="left|right" +			   font="SansSerifSmall" +			   height="15" +			   layout="topleft" +			   left_pad="5"  			 name="LabelOwnerName"  			 top_delta="6"  			 width="140"> @@ -224,7 +233,7 @@ top_pad="10"  			 top_delta="0"  			 width="222">  			Wed May 24 12:50:46 2006 -	    </text> +      </text>  	 <panel           border="false"           follows="left|top" @@ -350,7 +359,7 @@ top_pad="10"  			 tool_tip="Next owner can give away or resell this object"  			 width="106" />  	    </panel> -	    <check_box +	<check_box  			 height="18"  			 label="For Sale"  			 layout="topleft" @@ -388,144 +397,21 @@ top_pad="10"  			    height="23"  			    max_val="999999999"  			    top_pad="10"/> -	    <!--line_editor -			 border_style="line" -			 border_thickness="1" -			 follows="left|top|right" -			 height="16" -			 layout="topleft" -			 left_pad="5" -			 max_length="25" -			 name="EditPrice" -			 top_delta="0" -			 width="242" /--> -	    <!--text -			 type="string" -			 length="1" -			 follows="left|top" -			 height="10" -			 layout="topleft" -			 left="10" -			 name="BaseMaskDebug" -			 top="155" -			 width="330"> -			B: -	    </text> -	    <text -			 type="string" -			 length="1" -			 follows="left|top" -			 height="10" -			 layout="topleft" -			 left_delta="60" -			 name="OwnerMaskDebug" -			 top_delta="0" -			 width="270"> -			O: -	    </text> -	    <text -			 type="string" -			 length="1" -			 follows="left|top" -			 height="10" -			 layout="topleft" -			 left_delta="60" -			 name="GroupMaskDebug" -			 top_delta="0" -			 width="210"> -			G: -	    </text> -	    <text -			 type="string" -			 length="1" -			 follows="left|top" -			 height="10" -			 layout="topleft" -			 left_delta="60" -			 name="EveryoneMaskDebug" -			 top_delta="0" -			 width="150"> -			E: -	    </text> -	    <text -			 type="string" -			 length="1" -			 follows="left|top" -			 height="10" -			 layout="topleft" -			 left_delta="60" -			 name="NextMaskDebug" -			 top_delta="0" -			 width="90"> -			N: -	    </text--> -			    <!--text -			 type="string" -			 length="1" -			 follows="left|top" -			 height="10" -			 layout="topleft" -			 left="10" -			 name="SaleLabel" -			 top_pad="5" -			 width="330"> -			Mark Item: -	    </text--> -	    <!--radio_group -			 draw_border="false" -			 follows="left|top|right" -			 height="16" -			 layout="topleft" -			 left_delta="78" -			 name="RadioSaleType" -			 top_delta="0" -			 width="252"> -			    <radio_item -			     height="16" -			     label="Original" -			     layout="topleft" -			     left="0" -			     name="radio" -			     top="0" -			     width="70" /> -			    <radio_item -			     height="16" -			     label="Copy" -			     layout="topleft" -			     left_delta="60" -			     name="radio2" -			     top_delta="0" -			     width="70" /> -	    </radio_group--> -	    <!--text -			 type="string" -			 length="1" -			 follows="left|top" -			 height="16" -			 layout="topleft" -			 left="10" -			 name="TextPrice" -			 top_pad="5" -			 width="78"> -			Price: L$ -	    </text--> -	</panel> +   </panel>      <panel -		 height="25" +		 height="30"  		 layout="bottomright"  		 help_topic="button_tab"  		 name="button_panel"  		 left="5" -		 bottom="5" +		 bottom="2"  		 width="313">  	    <button -		     follows="bottom|right" -		     height="25" +		     height="23"  		     label="Cancel"  		     layout="topleft"  		     name="cancel_btn"  		     right="-1" -		     left_pad="10"  		     width="100" /> -	</panel> -</panel> +	    </panel> +	</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index 5b379b54e3..d26e855e2f 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -6,7 +6,7 @@  	 name="object properties"  	 help_topic="object_properties"  	 save_rect="true" -	 title="Object Properties" +	 title="Object Profile"  	 width="333">  	 <panel.string  	  name="text deed continued"> @@ -57,127 +57,173 @@                  Mixed Sale              </panel.string>      <button -	     follows="top|right" -	     height="25" -	     image_overlay="BackArrow_Off" -	     layout="topleft" -	     name="back_btn" -	     picture_style="true" -	     right="-5" -	     tab_stop="false" -	     top="0" -	     width="25" /> +     follows="top|right" +     height="23" +     image_overlay="BackArrow_Off" +     layout="topleft" +     left="10" +     name="back_btn" +     tab_stop="false" +     top="0" +     width="23" /> +        <text +     follows="top|left|right" +     font="SansSerifHuge" +     height="26" +     layout="topleft" +     left_pad="10" +     name="title" +     text_color="LtGray" +     top="0" +     use_ellipses="true" +     value="Object Profile" +     width="275" /> +	    <text +     follows="top|left" +     height="13" +     layout="topleft" +     left="45" +     name="where" +     text_color="LtGray_50" +     value="(In World)" +     width="150" />  	<panel           follows="all" -         height="500" +         height="490"           label=""           layout="topleft" -         left="5" +         left="10"           help_topic="" -         top="30" -		 border="1" -         width="313"> -            <text -             type="string" -             length="1" -             follows="left|top" -             height="10" -             layout="topleft" -             left="10" +         top="45" +         width="313" +   background_visible="true" +   bg_alpha_color="DkGray2"> +	    	    <text +		     type="string" +		     length="1" +		     follows="left|top" +		     height="10" +		     layout="topleft" +		     left="5"               name="Name:" -             top_pad="5" -             width="90"> -                Name: -            </text> -            <line_editor -             follows="left|top|right" -             height="19" -             layout="topleft" -             left_pad="0" -             max_length="63" +		     top="10" +		     width="78"> +	        Name: +	    </text> +	    <line_editor +		     border_style="line" +		     border_thickness="1" +	    	 follows="left|top|right" +		     height="20" +		     layout="topleft" +	    	 left_delta="78" +		     max_length="63"               name="Object Name" -             select_on_focus="true" -             top_delta="0" -             width="170" /> -            <text -             type="string" -             length="1" -             follows="left|top" -             height="10" -             layout="topleft" -             left="10" +	    	 top_delta="0" +		     width="225" /> +	    <text +	    type="string" +	    length="1" +	    follows="left|top" +	    height="10" +	    layout="topleft" +	    left="5"               name="Description:" -             top_pad="3" -             width="90"> -                Description: -            </text> +	    top_pad="10" +	    width="78"> +	        Description: +	    </text>              <line_editor +	     border_style="line" +    	     border_thickness="1"               follows="left|top|right" -             height="19" +             height="23"               layout="topleft" -             left_pad="0" -             max_length="127"               name="Object Description"               select_on_focus="true" -             top_delta="0" -             width="170" /> -            <text -             type="string" -             left="10" -             length="1" -             follows="left|top" -             height="19" -             layout="topleft" -             name="Creator:" -             width="90"> -                Creator: -            </text> -            <text -             type="string" -             length="1" -             follows="left|top" -             left_pad="0" -             height="19" -             layout="topleft" +    		 left_delta="78" +		     max_length="127" +	    	 top_delta="-5" +	    	 width="225"/> +	    <text +		     type="string" +		     length="1" +		     follows="left|top" +		     height="23" +		     layout="topleft" +    		 left="5" +		 name="CreatorNameLabel" +		  top_pad="10" +		     width="78"> +	        Creator: +    	</text> +	    	<avatar_icon +     follows="top|left" +     height="20" +     default_icon_name="Generic_Person" +     layout="topleft" +     left_pad="0" +      top_delta="-6" +     mouse_opaque="true" +     width="20" /> +	    <text +		     type="string" +     follows="left|right" +     font="SansSerifSmall" +     height="15" +     layout="topleft" +     left_pad="5"               name="Creator Name" -             width="175"> -                Esbee Linden -            </text> -            <text -             type="string" -             length="1" -             left="10" -             follows="left|top" -             height="19" -             layout="topleft" -             name="Owner:" -             width="90"> -                Owner: -            </text> -            <text -             type="string" -             length="1" -             follows="left|top" -             height="19" -             layout="topleft" -             name="Owner Name" -             left_pad="0" -             width="175"> -                Erica Linden -            </text> -           <text -             type="string" -             length="1" -             follows="left|top" -             layout="topleft" -             left="10" -             height="18" -             name="Group:" -             top_pad="4" -             width="75"> -                Group: -            </text> -            <button +		     top_delta="6" +		     width="140"> +	        Erica Linden +	     </text> +	    <text +			 type="string" +			 length="1" +			 follows="left|top" +			 height="23" +			layout="topleft" +			left="5" +			name="Owner:" +			top_pad="10" +			 width="78"> +			    Owner: +	     </text> +	     <avatar_icon +     follows="top|left" +     height="20" +     default_icon_name="Generic_Person" +     layout="topleft" +     left_pad="0" +	    top_delta="-6" +	    mouse_opaque="true" +     width="20" /> +	     <text +			    type="string" +			    follows="left|right" +			    font="SansSerifSmall" +			    height="15" +			    layout="topleft" +			    left_pad="5" +			    name="Owner Name" +			    top_delta="6" +			    width="140"> +			    Erica Linden +	     </text> +	    	    <text +			 type="string" +			 length="1" +			 follows="left|top" +			 height="23" +			 layout="topleft" +			 left="5" +			name="Group_label" +			top_pad="10" +			width="78"> +			    Group: +	     </text> +      		<button  			 follows="top|left"  			 height="10"  			 image_disabled="Activate_Checkmark" @@ -203,43 +249,34 @@               width="150" />              <button               follows="top|left" -             height="20" +             height="23"               label="Deed"               label_selected="Deed"               layout="topleft"               name="button deed"               top_pad="0" -             left="100" +             left="81"               tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer." -             width="80" /> -            <check_box -             height="19" -             follows="left|top" -             label="Share" -             layout="topleft" -             name="checkbox share with group" -             tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions." -             left_pad="3"               width="100" />              <text               type="string"               length="1"               follows="left|top" -             height="16" +             height="9"               layout="topleft" -             top_pad="15" -             left="10" +             top_pad="5" +             left="5"               name="label click action" -             width="90"> +             width="280">                  Click to:              </text>              <combo_box               follows="left|top" -             height="20" +             height="23"               layout="topleft"               name="clickaction"               width="168" -             left_pad="0"> +             left="81">                  <combo_box.item                   label="Touch  (default)"                   name="Touch/grab(default)" @@ -261,26 +298,131 @@                   name="Open"                   value="Open" />              </combo_box> -            <check_box -             height="16" +	 <panel +         border="false" +         follows="left|top" +         layout="topleft" +         mouse_opaque="false" +         background_visible="true" +         bg_alpha_color="DkGray" +         name="perms_inv" +         left="0" +         top_pad="15" +         height="135" +         width="313"> +	  <text +             type="string" +             length="1" +             left="10"               top_pad="15" -             label="For Sale:" +             text_color="EmphasisColor" +	     height="15" +             follows="left|top|right" +             layout="topleft" +             name="perm_modify" +             width="200"> +                You can modify this object +            </text> +	  	    <text +			 type="string" +			 length="1" +			 follows="left|top" +			 height="16" +			 layout="topleft" +			 left="10" +               name="Anyone can:" +			 top_pad="8" +			 width="100"> +			Anyone: +	    </text> +	    <check_box +			 height="18" +			 label="Copy" +			 layout="topleft" +			 left_pad="0" +             name="checkbox allow everyone copy" +			 top_delta="-2" +			 width="90" /> +	    <check_box +             height="18" +             label="Move"               layout="topleft" +             name="checkbox allow everyone move" +			 left_pad="0" +             width="150" /> +	       	<text +			 type="string" +			 length="1" +			 follows="left|top" +			 height="16" +			 layout="topleft" +			 left="10" +			 name="GroupLabel" +			 top_pad="8" +			 width="100"> +			Group: +    	</text> +			    <check_box +			 height="18" +			 label="Share" +			 layout="topleft" +			 left_pad="90" +			 top_delta="-2" +             name="checkbox share with group" +			 tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions." +			 width="150" /> +	    	    <text +			 type="string" +			 length="1" +			 follows="left|top" +			 height="16" +			 layout="topleft" +			 left="10" +			 name="NextOwnerLabel" +			 top_pad="8" +			 width="200" +			 word_wrap="true"> +			Next owner: +	    </text> +	    <check_box +			 height="18" +			 label="Modify" +			 layout="topleft" +			 left="20" +			 top_pad="0" +             name="checkbox next owner can modify" +			 width="90" /> +	    <check_box +			 height="18" +			 label="Copy" +			 layout="topleft" +			 left_pad="0" +             name="checkbox next owner can copy" +			 width="90" /> +	    <check_box +			 height="18" +			 label="Transfer" +			 layout="topleft" +			 left_pad="0" +             name="checkbox next owner can transfer" +			 tool_tip="Next owner can give away or resell this object" +			 width="106" /> +	    </panel> +	    <check_box +			 height="23" +			 label="For Sale" +			 layout="topleft" +			 left="20"               name="checkbox for sale" -             left="10" -             width="90" /> -<!-- NEW SALE TYPE COMBO BOX --> -      <combo_box -            left_pad="0" -            layout="topleft" -            follows="left|top" -            allow_text_entry="false" -            height="20" -            intial_value="2" -            max_chars="20" -            mouse_opaque="true" +			 top_pad="10" +			 width="100" /> +		<combo_box +			 height="23" +			 left_pad="0" +			 layout="topleft" +			 follows="left|top"              name="sale type" -            width="158"> +			 width="170">          <combo_box.item             name="Copy"             label="Copy" @@ -293,14 +435,13 @@             name="Original"             label="Original"             value="1" /> -      </combo_box> -<!-- NEW PRICE SPINNER --> -      <spinner +	    </combo_box> +		<spinner          follows="left|top"          decimal_digits="0"          increment="1" -        top_pad="8" -        left="100" +        top_pad="10" +        left="120"          control_name="Edit Cost"          name="Edit Cost"          label="Price: L$" @@ -310,106 +451,25 @@          height="20"          max_val="999999999" />        <check_box -	   height="15" +	   height="20"  	   width="110" -	   top_pad="3" +	   top_pad="6"  	   label="Show in search"         layout="topleft" -	   left="100" +	   left="120"         name="search_check"         tool_tip="Let people see this object in search results" /> -		<panel -         border="false" -         follows="left|top" -         layout="topleft" -         mouse_opaque="false" -         background_visible="true" -         bg_alpha_color="DkGray" -         name="perms_build" -         left="0" -         top="241" -         height="120" -         width="278"> -            <text -             type="string" -             length="1" -             left="10" -             top_pad="9" -             text_color="EmphasisColor" -             height="16" -             follows="left|top|right" -             layout="topleft" -             name="perm_modify" -             width="250"> -                You can modify this object -            </text> -            <text -               type="string" -               follows="left|top" -               name="Anyone can:" -               width="250" -               left="10"> -                 Anyone: -            </text> -            <check_box -             height="19" -             label="Move" -             layout="topleft" -             name="checkbox allow everyone move" -             left="15" -             width="85" /> -            <check_box -             height="19" -             label="Copy" -             layout="topleft" -             left_pad="0" -             name="checkbox allow everyone copy" -             width="90" /> -            <text -               type="string" -               follows="left|top" -               height="19" -               name="Next owner can:" -               width="250" -               left="10"> -                  Next owner: -            </text> -            <check_box -             follows="left|top|right" -             label="Modify" -             layout="topleft" -             left="15" -             name="checkbox next owner can modify" -             width="85" /> -            <check_box -             follows="left|top|right" -             height="19" -             label="Copy" -             layout="topleft" -             left_pad="0" -             name="checkbox next owner can copy" -             width="90" /> -            <check_box -             follows="left|top|right" -             height="19" -             label="Transfer" -             layout="topleft" -             name="checkbox next owner can transfer" -             left_pad="0" -             top_delta="0" -             tool_tip="Next owner can give away or resell this object" -             width="90" />              <text               type="string"               text_color="EmphasisColor"               length="1" -             top_pad="5" +             top_pad="15"               follows="left|top"               layout="topleft"               left="10"               name="B:"               height="10" -             width="45"> +             width="50">                  B:              </text>              <text @@ -421,7 +481,7 @@               left_pad="0"               name="O:"               height="10" -             width="44"> +             width="50">                  O:              </text>              <text @@ -433,7 +493,7 @@               left_pad="0"               name="G:"               height="10" -             width="43"> +             width="50">                  G:              </text>              <text @@ -445,7 +505,7 @@               layout="topleft"               name="E:"               height="10" -             width="43"> +             width="50">                  E:              </text>              <text @@ -457,7 +517,7 @@               left_pad="0"               name="N:"               height="10" -             width="48"> +             width="50">                  N:              </text>              <text @@ -473,7 +533,6 @@                  F:              </text>  		</panel> - </panel>      <panel  		 height="25"  		 layout="bottomright" @@ -484,30 +543,30 @@  		 width="313">          <button  		     follows="bottom|left" -		     height="25" +		     height="23"  		     label="Open"  		     layout="topleft"  		     left="5"  		     name="open_btn"  		     top="0" -		     width="60" /> +		     width="100" />  	    <button  		     follows="bottom|left" -		     height="25" +		     height="23"  		     label="Pay"  		     layout="topleft"  		     left_pad="5"  		     name="pay_btn"  		     top="0" -		     width="50" /> +		     width="100" />  	    <button  		     follows="bottom|left" -		     height="25" +		     height="23"  		     label="Buy"  		     layout="topleft"  		     left_pad="5"  		     name="buy_btn"  		     top="0" -		     width="60" /> +		     width="100" />  	</panel>  </panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 7438a36ed0..447901f984 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2085,7 +2085,7 @@ this texture in your inventory  	<string name="ATTACH_BELLY">Belly</string>  	<string name="ATTACH_RPEC">Right Pec</string>  	<string name="ATTACH_LPEC">Left Pec</string> -	<string name="ATTACH_HUD_CENTER_2"><HUD Center 2/string> +	<string name="ATTACH_HUD_CENTER_2">HUD Center 2</string>  	<string name="ATTACH_HUD_TOP_RIGHT">HUD Top Right</string>  	<string name="ATTACH_HUD_TOP_CENTER">HUD Top Center</string>  	<string name="ATTACH_HUD_TOP_LEFT">HUD Top Left</string> @@ -2904,13 +2904,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	<string name="joined_call">Joined the voice call</string>    <string name="ringing-im"> -    Joining Voice Chat... +    Joining voice call...    </string>    <string name="connected-im"> -    Connected, click End Call to hang up +    Connected, click Leave Call to hang up    </string>    <string name="hang_up-im"> -    Left Voice Chat +    Left voice call    </string>    <string name="answering-im">      Connecting... @@ -2964,22 +2964,49 @@ If you continue to receive this message, contact the [SUPPORT_SITE].    <string name="not_a_mod_error">      You are not a session moderator.    </string> +  <!--Some times string name is getting from the body of server response. +  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.  +  In case of the EXT-3562 issue 'muted' is passed into the gIMMgr::showSessionStartError as a string name. +  So, let add string with name="muted" with the same value as "muted_error" --> +  <string name="muted"> +    A group moderator disabled your text chat. +  </string>    <string name="muted_error">      A group moderator disabled your text chat.    </string>    <string name="add_session_event">      Unable to add users to chat session with [RECIPIENT].    </string> +  <!--Some times string name is getting from the body of server response. +  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.  +  In case of the EXT-3562 issue 'message' is passed into the gIMMgr::showSessionStartError as a string name. +  So, let add string with name="message" with the same value as "message_session_event" --> +  <string name="message"> +    Unable to send your message to the chat session with [RECIPIENT]. +  </string>      <string name="message_session_event">      Unable to send your message to the chat session with [RECIPIENT].    </string>    <string name="mute">      Error while moderating.    </string> +  <!--Some times string name is getting from the body of server response. +  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.  +  In case of the EXT-3459 issue 'removed' is passed into the gIMMgr::showSessionStartError as a string name. +  So, let add string with name="removed" with the same value as "removed_from_group" --> +  <string name="removed"> +    You have been removed from the group. +  </string>    <string name="removed_from_group">      You have been removed from the group.    </string>    <string name="close_on_no_ability">      You no longer have the ability to be in the chat session.    </string> +  <string name="unread_chat_single"> +    [SOURCES] has said something new +  </string>" +  <string name="unread_chat_multiple"> +    [SOURCES] have said something new +  </string>"  </strings> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml index 2be37d222a..8785dff2ae 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -11,9 +11,13 @@  	top_header_pad="17"  	bottom_header_pad="10"  	max_length="2147483647" -	enabled="false"  	track_bottom="true"  	name="chat_history"  	type="string"  	word_wrap="true" -  font="SansSerif"/> +  font="SansSerif"> +  <more_chat_text +    mouse_opaque="true"  +    word_wrap="true" +    /> +</chat_history> diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml new file mode 100644 index 0000000000..7cb973f4c8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_im_adhoc + font="SansSerif" + height="25" + name="im_adhoc_chiclet" + show_speaker="false" + width="25"> +    <chiclet_im_adhoc.speaker +     auto_update="true" +     draw_border="false" +     height="25" +     left="25" +     name="speaker" +     visible="false" +     width="20"/> +    <chiclet_im_adhoc.avatar_icon +     follows="left|top|bottom" +     height="22" +     mouse_opaque="true" +     name="adhoc_icon" +     width="22"/> +    <chiclet_im_adhoc.unread_notifications +     font="SansSerif" +     font_halign="center" +     height="25" +     left="25" +     mouse_opaque="false" +     name="unread" +     text_color="white" +     v_pad="5" +     visible="false" +     width="20"/> +    <chiclet_im_adhoc.new_message_icon +     bottom="12" +     height="13" +     image_name="Unread_IM" +     left="12" +     name="new_message_icon" +     visible="false" +     width="13" /> +</chiclet_im_adhoc>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml new file mode 100644 index 0000000000..a9b567225e --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_im_group + font="SansSerif" + height="25" + name="im_group_chiclet" + show_speaker="false" + width="25"> +    <chiclet_im_group.speaker +     auto_update="true" +     draw_border="false" +     height="25" +     left="25" +     name="speaker" +     visible="false" +     width="20"/> +    <chiclet_im_group.group_icon +     default_icon="Generic_Group" +     follows="left|top|bottom" +     height="22" +     mouse_opaque="true" +     name="group_icon" +     width="22"/> +    <chiclet_im_group.unread_notifications +     height="25" +     font="SansSerif" +     font_halign="center" +     left="25" +     mouse_opaque="false" +     name="unread" +     text_color="white" +     v_pad="5" +     visible="false" +     width="20"/> +    <chiclet_im_group.new_message_icon +     bottom="12" +     height="13" +     image_name="Unread_IM" +     left="12" +     name="new_message_icon" +     visible="false" +     width="13" /> +</chiclet_im_group>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml new file mode 100644 index 0000000000..9283594a4c --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_im_p2p + font="SansSerif" + height="25" + name="im_p2p_chiclet" + show_speaker="false" + width="25"> +    <chiclet_im_p2p.speaker +     auto_update="true" +     draw_border="false" +     height="25" +     left="25" +     name="speaker" +     visible="false" +     width="20"/> +    <chiclet_im_p2p.avatar_icon +     follows="left|top|bottom" +     height="22" +     mouse_opaque="true" +     name="avatar_icon" +     width="22"/> +    <chiclet_im_p2p.unread_notifications +     height="25" +     font="SansSerif" +     font_halign="center" +     left="25" +     mouse_opaque="false" +     name="unread" +     text_color="white" +     v_pad="5" +     visible="false" +     width="20"/> +    <chiclet_im_p2p.new_message_icon +     bottom="12" +     height="13" +     image_name="Unread_IM" +     left="12" +     name="new_message_icon" +     visible="false" +     width="13" /> +</chiclet_im_p2p>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml new file mode 100644 index 0000000000..5a22563758 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_offer + font="SansSerif" + height="25" + name="offer_chiclet" + width="25"> + <chiclet_offer.icon +  default_icon="Generic_Object_Small"  +  follows="all" +  height="22" +  mouse_opaque="false" +  name="chiclet_icon" +  width="22"/> + <chiclet_offer.new_message_icon +  bottom="12" +  height="13" +  image_name="Unread_IM" +  left="12" +  name="new_message_icon" +  visible="false" +  width="13" /> +</chiclet_offer>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml new file mode 100644 index 0000000000..f3207ddeae --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_panel + name="chiclet_panel"  + chiclet_padding="3" + scrolling_offset="40" + scroll_button_hpad="5" + scroll_ratio="10" + min_width="180" + />
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml index e5af961a56..05a23b95f9 100644 --- a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml @@ -1,10 +1,22 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 -<chiclet_script
 - name="script_chiclet"
 - font="SansSerif">
 - <icon
 -  name="chiclet_icon"
 -  follows="all"
 -  mouse_opaque="false"
 -  image_name="Generic_Object_Small" />
 -</expandable_text>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_script + font="SansSerif" + height="25" + name="script_chiclet" + width="25"> + <chiclet_script.icon +  follows="all" +  height="22" +  image_name="Generic_Object_Small"  +  mouse_opaque="false" +  name="chiclet_icon" +  width="22"/> + <chiclet_script.new_message_icon +  bottom="12" +  height="13" +  image_name="Unread_IM" +  left="12" +  name="new_message_icon" +  visible="false" +  width="13" /> +</chiclet_script>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml index 21b957d089..9d71ceca2f 100644 --- a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml +++ b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml @@ -1,9 +1,13 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <output_monitor +  draw_border="true" +  follows="top|left"    image_mute="Parcel_VoiceNo_Light"    image_off="VoicePTT_Off"    image_on="VoicePTT_On"    image_level_1="VoicePTT_Lvl1"    image_level_2="VoicePTT_Lvl2"    image_level_3="VoicePTT_Lvl3" +  mouse_opaque="false" +  name="output_monitor"    /> diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml index 3368fa88ef..3f5a4b8379 100644 --- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml @@ -20,12 +20,12 @@ label_pad_left - padding to the left of tab button labels                 tab_top_image_selected="TabTop_Middle_Selected"                 tab_bottom_image_unselected="Toolbar_Middle_Off"                 tab_bottom_image_selected="Toolbar_Middle_Selected" -               tab_left_image_unselected="TabTop_Middle_Off" -               tab_left_image_selected="TabTop_Middle_Selected"/> +               tab_left_image_unselected="SegmentedBtn_Left_Disabled" +               tab_left_image_selected="SegmentedBtn_Left_Off"/>    <last_tab tab_top_image_unselected="TabTop_Right_Off"                 tab_top_image_selected="TabTop_Right_Selected"                 tab_bottom_image_unselected="Toolbar_Right_Off"                 tab_bottom_image_selected="Toolbar_Right_Selected" -               tab_left_image_unselected="TabTop_Middle_Off" -               tab_left_image_selected="TabTop_Middle_Selected"/> +               tab_left_image_unselected="SegmentedBtn_Left_Disabled" +               tab_left_image_selected="SegmentedBtn_Left_Off"/>  </tab_container> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index d2859db296..0db18525d7 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -354,6 +354,14 @@ class WindowsManifest(ViewerManifest):                      self.path("qtiffd4.dll")                      self.end_prefix() +                # For WebKit/Qt plugin runtimes (codec/character encoding plugins) +                if self.prefix(src="codecs", dst="codecs"): +                    self.path("qcncodecsd4.dll") +                    self.path("qjpcodecsd4.dll") +                    self.path("qkrcodecsd4.dll") +                    self.path("qtwcodecsd4.dll") +                    self.end_prefix() +                  self.end_prefix()          else:              if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'release'), @@ -377,6 +385,14 @@ class WindowsManifest(ViewerManifest):                      self.path("qtiff4.dll")                      self.end_prefix() +                # For WebKit/Qt plugin runtimes (codec/character encoding plugins) +                if self.prefix(src="codecs", dst="codecs"): +                    self.path("qcncodecs4.dll") +                    self.path("qjpcodecs4.dll") +                    self.path("qkrcodecs4.dll") +                    self.path("qtwcodecs4.dll") +                    self.end_prefix() +                  self.end_prefix()          self.disable_manifest_check() diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt index 89e2d8582d..b4043b0fd9 100644 --- a/indra/test_apps/llplugintest/CMakeLists.txt +++ b/indra/test_apps/llplugintest/CMakeLists.txt @@ -428,7 +428,23 @@ if(WINDOWS)      ${plugintest_debug_files}      )    set(plugin_test_targets ${plugin_test_targets} ${out_targets}) -   + +  # Debug config runtime files required for the plugin test mule (Qt codec plugins) +  set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/codecs") +  set(plugintest_debug_files +    qcncodecsd4.dll +    qjpcodecsd4.dll +    qkrcodecsd4.dll +    qtwcodecsd4.dll +    ) +  copy_if_different( +    ${plugintest_debug_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/Debug/codecs" +    out_targets +    ${plugintest_debug_files} +    ) +  set(plugin_test_targets ${plugin_test_targets} ${out_targets}) +     # Release & ReleaseDebInfo config runtime files required for the plugin test mule    set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")    set(plugintest_release_files @@ -486,6 +502,30 @@ if(WINDOWS)      ${plugintest_release_files}      )    set(plugin_test_targets ${plugin_test_targets} ${out_targets}) + +  # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt codec plugins) +  set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/codecs") +  set(plugintest_release_files +    qcncodecs4.dll   +    qjpcodecs4.dll   +    qkrcodecs4.dll   +    qtwcodecs4.dll   +    ) +  copy_if_different( +    ${plugintest_release_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/Release/codecs" +    out_targets +    ${plugintest_release_files} +    ) +  set(plugin_test_targets ${plugin_test_targets} ${out_targets}) + +  copy_if_different( +    ${plugintest_release_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/codecs" +    out_targets +    ${plugintest_release_files} +    ) +  set(plugin_test_targets ${plugin_test_targets} ${out_targets})     add_custom_target(copy_plugintest_libs ALL       DEPENDS  diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index 018f691672..364088ab31 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -235,6 +235,8 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential                  break;              } +			sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]); +              // Here the login service at the current URI is redirecting us              // to some other URI ("indeterminate" -- why not "redirect"?).              // The response should contain another uri to try, with its @@ -276,7 +278,14 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential      // Here we got through all the rewrittenURIs without succeeding. Tell      // caller this didn't work out so well. Of course, the only failure data      // we can reasonably show are from the last of the rewrittenURIs. -    sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]); + +	// *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an +	// llsd with no "responses" node. To make the output from an incomplete login symmetrical  +	// to success, add a data/message and data/reason fields. +	LLSD error_response; +	error_response["reason"] = mAuthResponse["status"]; +	error_response["message"] = mAuthResponse["error"]; +	sendProgressEvent("offline", "fail.login", error_response);  }  void LLLogin::Impl::disconnect() diff --git a/install.xml b/install.xml index 0501ef9cfd..fdd7458384 100644 --- a/install.xml +++ b/install.xml @@ -948,9 +948,9 @@ anguage Infrstructure (CLI) international standard</string>            <key>darwin</key>            <map>              <key>md5sum</key> -            <string>1631831b63310d85ad272b4dca3c1fbf</string> +            <string>5362a53488693f9bd7d9083758af25eb</string>              <key>url</key> -            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20091217.tar.bz2</uri> +            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20091218.tar.bz2</uri>            </map>            <key>linux</key>            <map> @@ -962,9 +962,9 @@ anguage Infrstructure (CLI) international standard</string>            <key>windows</key>            <map>              <key>md5sum</key> -            <string>3846354e2e20a98c0401317eb114ff5e</string> +            <string>4dd305f2ce38b2e55a2014ad3a2de34d</string>              <key>url</key> -            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-qt4.6-20091215.tar.bz2</uri> +            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-qt4.6-20091218.tar.bz2</uri>            </map>          </map>        </map> | 
