diff options
382 files changed, 17927 insertions, 15139 deletions
diff --git a/BuildParams b/BuildParams index ebfc640023..dbf7a4cbc4 100644 --- a/BuildParams +++ b/BuildParams @@ -136,6 +136,18 @@ viewer-pathfinding.build_debug_release_separately = true  viewer-pathfinding.build_CYGWIN_Debug = false  viewer-pathfinding.build_viewer_update_version_manager = false +# ======================================== +# viewer-chui +# +# ======================================== + +viewer-chui.viewer_channel = "Project Viewer - CHUI" +viewer-chui.login_channel = "Project Viewer - CHUI" +viewer-chui.viewer_grid = agni +viewer-chui.build_debug_release_separately = true +viewer-chui.build_CYGWIN_Debug = false +viewer-chui.build_viewer_update_version_manager = false +  # =================================================================  # asset delivery 2010 projects  # ================================================================= diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 0745696ef3..0da83720bd 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -62,6 +62,7 @@ enum LAND_STAT_FLAGS  	STAT_FILTER_BY_PARCEL	= 0x00000001,  	STAT_FILTER_BY_OWNER	= 0x00000002,  	STAT_FILTER_BY_OBJECT	= 0x00000004, +	STAT_FILTER_BY_PARCEL_NAME	= 0x00000008,  	STAT_REQUEST_LAST_ENTRY	= 0x80000000,  }; diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 5e566d6c7c..5ae2df3994 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -95,6 +95,7 @@ LLAssetDictionary::LLAssetDictionary()  	addEntry(LLAssetType::AT_LINK_FOLDER, 		new AssetEntry("FOLDER_LINK",		"link_f", 	"sym folder link",	false,		false,		true));  	addEntry(LLAssetType::AT_MESH,              new AssetEntry("MESH",              "mesh",     "mesh",             false,      false,      false));  	addEntry(LLAssetType::AT_WIDGET,            new AssetEntry("WIDGET",            "widget",   "widget",           false,      false,      false)); +	addEntry(LLAssetType::AT_PERSON,            new AssetEntry("PERSON",            "person",   "person",           false,      false,      false));  	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		FALSE,		FALSE,		FALSE));  }; diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index d538accbf7..69b01731e5 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -112,6 +112,9 @@ public:  		AT_WIDGET = 40,  			// UI Widget: this is *not* an inventory asset type, only a viewer side asset (e.g. button, other ui items...) +		AT_PERSON = 45, +			// A user uuid  which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop. +  		AT_MESH = 49,  			// Mesh data in our proprietary SLM format diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index db72aa19b9..89c831d296 100644 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -40,7 +40,9 @@ namespace LLInitParam  	{  		const U8* my_addr = reinterpret_cast<const U8*>(this);  		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); -		mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr); +		U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); +		mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; +		mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16;  	}  	// @@ -112,6 +114,35 @@ namespace LLInitParam  		std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));  	} +	void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name) +	{ +		// create a copy of the param descriptor in mAllParams +		// so other data structures can store a pointer to it +		mAllParams.push_back(in_param); +		ParamDescriptorPtr param(mAllParams.back()); + +		std::string name(char_name); +		if ((size_t)param->mParamHandle > mMaxParamOffset) +		{ +			llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; +		} + +		if (name.empty()) +		{ +			mUnnamedParams.push_back(param); +		} +		else +		{ +			// don't use insert, since we want to overwrite existing entries +			mNamedParams[name] = param; +		} + +		if (param->mValidationFunc) +		{ +			mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); +		} +	} +  	BlockDescriptor::BlockDescriptor()  	:	mMaxParamOffset(0),  		mInitializationState(UNINITIALIZED), @@ -150,7 +181,8 @@ namespace LLInitParam  	bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)  	{ -		if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true)) +		Parser::name_stack_range_t range = std::make_pair(name_stack.begin(), name_stack.end()); +		if (!deserializeBlock(p, range, true))  		{  			if (!silent)  			{ @@ -196,12 +228,7 @@ namespace LLInitParam  			if (serialize_func)  			{  				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; -				// each param descriptor remembers its serial number -				// so we can inspect the same param under different names -				// and see that it has the same number -				name_stack.push_back(std::make_pair("", true));  				serialize_func(*param, parser, name_stack, diff_param); -				name_stack.pop_back();  			}  		} @@ -295,7 +322,7 @@ namespace LLInitParam  		return true;  	} -	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored) +	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool ignored)  	{  		BlockDescriptor& block_data = mostDerivedBlockDescriptor();  		bool names_left = name_stack_range.first != name_stack_range.second; @@ -308,15 +335,12 @@ namespace LLInitParam  		{  			const std::string& top_name = name_stack_range.first->first; -			ParamDescriptor::deserialize_func_t deserialize_func = NULL; -			Param* paramp = NULL; -  			BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);  			if (found_it != block_data.mNamedParams.end())  			{  				// find pointer to member parameter from offset table -				paramp = getParamFromHandle(found_it->second->mParamHandle); -				deserialize_func = found_it->second->mDeserializeFunc; +				Param* paramp = getParamFromHandle(found_it->second->mParamHandle); +				ParamDescriptor::deserialize_func_t deserialize_func = found_it->second->mDeserializeFunc;  				Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);  				++new_name_stack.first; @@ -358,36 +382,6 @@ namespace LLInitParam  		return false;  	} -	//static  -	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name) -	{ -		// create a copy of the param descriptor in mAllParams -		// so other data structures can store a pointer to it -		block_data.mAllParams.push_back(in_param); -		ParamDescriptorPtr param(block_data.mAllParams.back()); - -		std::string name(char_name); -		if ((size_t)param->mParamHandle > block_data.mMaxParamOffset) -		{ -			llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; -		} - -		if (name.empty()) -		{ -			block_data.mUnnamedParams.push_back(param); -		} -		else -		{ -			// don't use insert, since we want to overwrite existing entries -			block_data.mNamedParams[name] = param; -		} - -		if (param->mValidationFunc) -		{ -			block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); -		} -	} -  	void BaseBlock::addSynonym(Param& param, const std::string& synonym)  	{  		BlockDescriptor& block_data = mostDerivedBlockDescriptor(); @@ -460,7 +454,7 @@ namespace LLInitParam  			if (merge_func)  			{  				Param* paramp = getParamFromHandle((*it)->mParamHandle); -				llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle); +				llassert(paramp->getEnclosingBlockOffset() == (*it)->mParamHandle);  				some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);  			}  		} diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 99983a19cb..be07ccc0f8 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -35,7 +35,72 @@  #include <boost/shared_ptr.hpp>  #include "llerror.h" -#include "lltypeinfolookup.h" +#include "llstl.h" + +namespace LLTypeTags +{ +	template <typename INNER_TYPE, int _SORT_ORDER> +	struct TypeTagBase +	{ +		typedef void		is_tag_t; +		typedef INNER_TYPE	inner_t; +		static const int	SORT_ORDER=_SORT_ORDER; +	}; + +	template <int VAL1, int VAL2> +	struct GreaterThan +	{ +		static const bool value = VAL1 > VAL2; +	}; + +	template<typename ITEM, typename REST, bool NEEDS_SWAP = GreaterThan<ITEM::SORT_ORDER, REST::SORT_ORDER>::value > +	struct Swap +	{ +		typedef typename ITEM::template Cons<REST>::value_t value_t; +	}; + +	template<typename ITEM, typename REST> +	struct Swap<ITEM, REST, true> +	{ +		typedef typename REST::template Cons<Swap<ITEM, typename REST::inner_t>::value_t>::value_t value_t; +	}; + +	template<typename T, typename SORTABLE = void> +	struct IsSortable +	{ +		static const bool value = false; +	}; + +	template<typename T> +	struct IsSortable<T, typename T::is_tag_t> +	{ +		static const bool value = true; +	}; + +	template<typename ITEM, typename REST, bool IS_REST_SORTABLE = IsSortable<REST>::value> +	struct InsertInto +	{ +		typedef typename ITEM::template Cons<REST>::value_t value_t; +	}; + +	template<typename ITEM, typename REST> +	struct InsertInto <ITEM, REST, true> +	{ +		typedef typename Swap<ITEM, REST>::value_t value_t; +	}; + +	template<typename T, bool SORTABLE = IsSortable<T>::value> +	struct Sorted +	{ +		typedef T value_t; +	}; + +	template<typename T> +	struct Sorted <T, true> +	{ +		typedef typename InsertInto<T, typename Sorted<typename T::inner_t>::value_t>::value_t value_t; +	}; +}  namespace LLInitParam  { @@ -44,6 +109,8 @@ namespace LLInitParam  	template<typename T> const T& defaultValue() { static T value; return value; } +	// wraps comparison operator between any 2 values of the same type +	// specialize to handle cases where equality isn't defined well, or at all  	template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >      struct ParamCompare   	{ @@ -78,24 +145,123 @@ namespace LLInitParam  	// helper functions and classes  	typedef ptrdiff_t param_handle_t; +	struct IS_A_BLOCK {}; +	struct NOT_BLOCK {}; + +	// these templates allow us to distinguish between template parameters +	// that derive from BaseBlock and those that don't +	template<typename T, typename BLOCK_IDENTIFIER = void> +	struct IsBlock +	{ +		typedef NOT_BLOCK value_t; +	}; + +	template<typename T> +	struct IsBlock<T, typename T::baseblock_base_class_t> +	{ +		typedef IS_A_BLOCK value_t; +	}; + +	// ParamValue class directly manages the wrapped value +	// by holding on to a copy (scalar params) +	// or deriving from it (blocks) +	// has specializations for custom value behavior +	// and "tag" values like Lazy and Atomic +	template<typename T, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> +	class ParamValue +	{ +		typedef ParamValue<T, VALUE_IS_BLOCK>	self_t; + +	public: +		typedef T	default_value_t; +		typedef T	value_t; + +		ParamValue(): mValue() {} +		ParamValue(const default_value_t& other) : mValue(other) {} + +		void setValue(const value_t& val) +		{ +			mValue = val; +		} + +		const value_t& getValue() const +		{ +			return mValue; +		} + +		T& getValue() +		{ +			return mValue; +		} + +	protected: +		T mValue; +	}; + +	template<typename T> +	class ParamValue<T, IS_A_BLOCK>  +	:	public T +	{ +		typedef ParamValue<T, IS_A_BLOCK>	self_t; +	public: +		typedef T	default_value_t; +		typedef T	value_t; + +		ParamValue()  +		:	T(), +			mValidated(false) +		{} + +		ParamValue(const default_value_t& other) +		:	T(other), +			mValidated(false) +		{} + +		void setValue(const value_t& val) +		{ +			*this = val; +		} + +		const value_t& getValue() const +		{ +			return *this; +		} + +		T& getValue() +		{ +			return *this; +		} + +	protected: +		mutable bool 	mValidated; // lazy validation flag +	}; +  	// empty default implementation of key cache  	// leverages empty base class optimization  	template <typename T>  	class TypeValues +	:	public ParamValue<typename LLTypeTags::Sorted<T>::value_t>  	{  	private:  		struct Inaccessable{};  	public:  		typedef std::map<std::string, T> value_name_map_t;  		typedef Inaccessable name_t; +		typedef TypeValues<T> type_value_t; +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>	param_value_t; +		typedef typename param_value_t::value_t	value_t; + +		TypeValues(const typename param_value_t::value_t& val) +		:	param_value_t(val) +		{}  		void setValueName(const std::string& key) {}  		std::string getValueName() const { return ""; } -		std::string calcValueName(const T& value) const { return ""; } +		std::string calcValueName(const value_t& value) const { return ""; }  		void clearValueName() const {} -		static bool getValueFromName(const std::string& name, T& value) +		static bool getValueFromName(const std::string& name, value_t& value)  		{  			return false;  		} @@ -110,15 +276,39 @@ namespace LLInitParam  			return NULL;  		} +		void assignNamedValue(const Inaccessable& name) +		{} + +		operator const value_t&() const +		{ +			return param_value_t::getValue(); +		} + +		const value_t& operator()() const +		{ +			return param_value_t::getValue(); +		} +  		static value_name_map_t* getValueNames() {return NULL;}  	}; -	template <typename T, typename DERIVED_TYPE = TypeValues<T> > +	// helper class to implement name value lookups +	// and caching of last used name +	template <typename T, typename DERIVED_TYPE = TypeValues<T>, bool IS_SPECIALIZED = true >  	class TypeValuesHelper +	:	public ParamValue<typename LLTypeTags::Sorted<T>::value_t>  	{ +		typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t;  	public:  		typedef typename std::map<std::string, T> value_name_map_t;  		typedef std::string name_t; +		typedef self_t type_value_t; +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; +		typedef typename param_value_t::value_t	value_t; + +		TypeValuesHelper(const typename param_value_t::value_t& val) +		:	param_value_t(val) +		{}  		//TODO: cache key by index to save on param block size  		void setValueName(const std::string& value_name)  @@ -131,7 +321,7 @@ namespace LLInitParam  			return mValueName;   		} -		std::string calcValueName(const T& value) const +		std::string calcValueName(const value_t& value) const  		{  			value_name_map_t* map = getValueNames();  			for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); @@ -152,7 +342,7 @@ namespace LLInitParam  			mValueName.clear();  		} -		static bool getValueFromName(const std::string& name, T& value) +		static bool getValueFromName(const std::string& name, value_t& value)  		{  			value_name_map_t* map = getValueNames();  			typename value_name_map_t::iterator found_it = map->find(name); @@ -194,32 +384,96 @@ namespace LLInitParam  			return &sValues;  		} -		static void declare(const std::string& name, const T& value) +		static void declare(const std::string& name, const value_t& value)  		{  			(*getValueNames())[name] = value;  		} +		void operator ()(const std::string& name) +		{ +			*this = name; +		} + +		void assignNamedValue(const std::string& name) +		{ +			if (getValueFromName(name, param_value_t::getValue())) +			{ +				setValueName(name); +			} +		} + +		operator const value_t&() const +		{ +			return param_value_t::getValue(); +		} + +		const value_t& operator()() const +		{ +			return param_value_t::getValue(); +		} +  	protected: -		static void getName(const std::string& name, const T& value) +		static void getName(const std::string& name, const value_t& value)  		{}  		mutable std::string	mValueName;  	}; -	class LL_COMMON_API Parser +	// string types can support custom named values, but need +	// to disambiguate in code between a string that is a named value +	// and a string that is a name +	template <typename DERIVED_TYPE> +	class TypeValuesHelper<std::string, DERIVED_TYPE, true> +	:	public TypeValuesHelper<std::string, DERIVED_TYPE, false>  	{ -		LOG_CLASS(Parser); -  	public: -		 -		struct CompareTypeID +		typedef TypeValuesHelper<std::string, DERIVED_TYPE, true> self_t; +		typedef TypeValuesHelper<std::string, DERIVED_TYPE, false> base_t; +		typedef std::string value_t; +		typedef std::string name_t; +		typedef self_t type_value_t; + +		TypeValuesHelper(const std::string& val) +		:	TypeValuesHelper(val) +		{} + +		void operator ()(const std::string& name)  		{ -			bool operator()(const std::type_info* lhs, const std::type_info* rhs) const +			*this = name; +		} + +		self_t& operator =(const std::string& name) +		{ +			if (base_t::getValueFromName(name, ParamValue<std::string>::getValue()))  			{ -				return lhs->before(*rhs); +				base_t::setValueName(name);  			} -		}; +			else +			{ +				ParamValue<std::string>::setValue(name); +			} +			return *this; +		} +		 +		operator const value_t&() const +		{ +			return ParamValue<std::string>::getValue(); +		} + +		const value_t& operator()() const +		{ +			return ParamValue<std::string>::getValue(); +		} +	}; + +	// parser base class with mechanisms for registering readers/writers/inspectors of different types +	class LL_COMMON_API Parser +	{ +		LOG_CLASS(Parser); + +	public: +		  		typedef std::vector<std::pair<std::string, bool> >					name_stack_t;  		typedef std::pair<name_stack_t::iterator, name_stack_t::iterator>	name_stack_range_t;  		typedef std::vector<std::string>									possible_values_t; @@ -228,9 +482,9 @@ namespace LLInitParam  		typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);  		typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t; -		typedef LLTypeInfoLookup<parser_read_func_t>		parser_read_func_map_t; -		typedef LLTypeInfoLookup<parser_write_func_t>		parser_write_func_map_t; -		typedef LLTypeInfoLookup<parser_inspect_func_t>		parser_inspect_func_map_t; +		typedef std::map<const std::type_info*, parser_read_func_t>		parser_read_func_map_t; +		typedef std::map<const std::type_info*, parser_write_func_t>	parser_write_func_map_t; +		typedef std::map<const std::type_info*, parser_inspect_func_t>	parser_inspect_func_map_t;  		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)  		:	mParseSilently(false), @@ -310,7 +564,7 @@ namespace LLInitParam  		};  		typedef bool(*merge_func_t)(Param&, const Param&, bool); -		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool); +		typedef bool(*deserialize_func_t)(Param&, Parser&, Parser::name_stack_range_t&, bool);  		typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);  		typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);  		typedef bool(*validation_func_t)(const Param*); @@ -355,6 +609,7 @@ namespace LLInitParam  		} EInitializationState;  		void aggregateBlockData(BlockDescriptor& src_block_data); +		void addParam(ParamDescriptorPtr param, const char* name);  		typedef boost::unordered_map<const std::string, ParamDescriptorPtr>						param_map_t;   		typedef std::vector<ParamDescriptorPtr>													param_list_t;  @@ -370,86 +625,144 @@ namespace LLInitParam  		class BaseBlock*				mCurrentBlockPtr;		// pointer to block currently being constructed  	}; -	class LL_COMMON_API BaseBlock +	//TODO: implement in terms of owned_ptr +	template<typename T> +	class LazyValue  	{ -	public: -		//TODO: implement in terms of owned_ptr -		template<typename T> -		class Lazy -		{  		public: -			Lazy() -				: mPtr(NULL) -			{} +		LazyValue() +		: mPtr(NULL) +		{} + +		~LazyValue() +		{ +			delete mPtr; +		} + +		LazyValue(const T& value) +		{ +			mPtr = new T(value); +		} + +		LazyValue(const LazyValue& other) +		:	mPtr(NULL) +		{ +			*this = other; +		} -			~Lazy() +		LazyValue& operator = (const LazyValue& other) +		{ +			if (!other.mPtr)  			{  				delete mPtr; +				mPtr = NULL;  			} - -			Lazy(const Lazy& other) +			else  			{ -				if (other.mPtr) +				if (!mPtr)  				{  					mPtr = new T(*other.mPtr);  				}  				else  				{ -					mPtr = NULL; +					*mPtr = *(other.mPtr);  				}  			} +			return *this; +		} -			Lazy<T>& operator = (const Lazy<T>& other) -			{ -				if (other.mPtr) -				{ -					mPtr = new T(*other.mPtr); -				} -				else -				{ -					mPtr = NULL; -				} -				return *this; -			} +		bool operator==(const LazyValue& other) const +		{ +			if (empty() || other.empty()) return false; +			return *mPtr == *other.mPtr; +		} -			bool empty() const -			{ -				return mPtr == NULL; -			} +		bool empty() const +		{ +			return mPtr == NULL; +		} -			void set(const T& other) +		void set(const T& other) +		{ +			if (!mPtr)  			{ -				delete mPtr;  				mPtr = new T(other);  			} - -			const T& get() const +			else  			{ -				return ensureInstance(); +				*mPtr = other;  			} +		} -			T& get() -			{ -				return ensureInstance(); -			} +		const T& get() const +		{ +			return *ensureInstance(); +		} -		private: -			// lazily allocate an instance of T -			T* ensureInstance() const +		T& get() +		{ +			return *ensureInstance(); +		} + +		operator const T&() const +		{  +			return get();  +		} + +	private: +		// lazily allocate an instance of T +		T* ensureInstance() const +		{ +			if (mPtr == NULL)  			{ -				if (mPtr == NULL) -				{ -					mPtr = new T(); -				} -				return mPtr; -			} +				mPtr = new T();			 +                        } +			return mPtr; +		} -		private: -			// if you get a compilation error with this, that means you are using a forward declared struct for T -			// unfortunately, the type traits we rely on don't work with forward declared typed -			//static const int dummy = sizeof(T); +	private: + +		mutable T* mPtr; +	}; + +	// root class of all parameter blocks + +	class LL_COMMON_API BaseBlock +	{ +	public: +		// lift block tags into baseblock namespace so derived classes do not need to qualify them +		typedef LLInitParam::IS_A_BLOCK IS_A_BLOCK; +		typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK; + +		template<typename T> +		struct Sequential : public LLTypeTags::TypeTagBase<T, 2> +		{ +			template <typename S> struct Cons { typedef Sequential<ParamValue<S> > value_t; }; +			template <typename S> struct Cons<Sequential<S> > { typedef Sequential<S> value_t; }; +		}; -			mutable T* mPtr; +		template<typename T> +		struct Atomic : public LLTypeTags::TypeTagBase<T, 1> +		{ +			template <typename S> struct Cons { typedef Atomic<ParamValue<S> > value_t; }; +			template <typename S> struct Cons<Atomic<S> > { typedef Atomic<S> value_t; }; +		}; + +		template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t > +		struct Lazy : public LLTypeTags::TypeTagBase<T, 0> +		{ +			template <typename S> struct Cons +			{ +				typedef Lazy<ParamValue<S, BLOCK_T>, BLOCK_T> value_t; +			}; +			template <typename S> struct Cons<Lazy<S, IS_A_BLOCK> > +			{ +				typedef Lazy<S, IS_A_BLOCK> value_t; +			}; +			template <typename S> struct Cons<Lazy<S, NOT_A_BLOCK> > +			{ +				typedef Lazy<S, BLOCK_T> value_t; +			};  		};  		// "Multiple" constraint types, put here in root class to avoid ambiguity during use @@ -517,12 +830,12 @@ namespace LLInitParam  		// Blocks can override this to do custom tracking of changes  		virtual void paramChanged(const Param& changed_param, bool user_provided) {} -		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name);  		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;  		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; -		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } -		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } +		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } +		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }  		// take all provided params from other and apply to self  		bool overwriteFrom(const BaseBlock& other) @@ -536,10 +849,17 @@ namespace LLInitParam  			return false;  		} -		static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name); -  		ParamDescriptorPtr findParamDescriptor(const Param& param); +		// take all provided params from other and apply to self +		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); + +		static BlockDescriptor& getBlockDescriptor() +		{ +			static BlockDescriptor sBlockDescriptor; +			return sBlockDescriptor; +		} +  	protected:  		void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); @@ -548,25 +868,11 @@ namespace LLInitParam  		{  			return mergeBlock(block_data, source, overwrite);  		} -		// take all provided params from other and apply to self -		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); - -		static BlockDescriptor& selfBlockDescriptor() -		{ -			static BlockDescriptor sBlockDescriptor; -			return sBlockDescriptor; -		}  	private:  		const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;  	}; -	template<typename T> -	struct ParamCompare<BaseBlock::Lazy<T>, false > -	{ -		static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) { return !a.empty() || !b.empty(); } -	}; -  	class LL_COMMON_API Param  	{  	public: @@ -595,256 +901,68 @@ namespace LLInitParam  			// get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class  			return *const_cast<BaseBlock*>  				(reinterpret_cast<const BaseBlock*> -					(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); -		} - -	private: -		friend class BaseBlock; - -		U32		mEnclosingBlockOffset:31; -		U32		mIsProvided:1; - -	}; - -	// these templates allow us to distinguish between template parameters -	// that derive from BaseBlock and those that don't -	template<typename T, typename Void = void> -	struct IsBlock -	{ -		static const bool value = false; -		struct EmptyBase {}; -		typedef EmptyBase base_class_t; -	}; - -	template<typename T> -	struct IsBlock<T, typename T::baseblock_base_class_t> -	{ -		static const bool value = true; -		typedef BaseBlock base_class_t; -	}; - -	template<typename T> -	struct IsBlock<BaseBlock::Lazy<T>, typename T::baseblock_base_class_t > -	{ -		static const bool value = true; -		typedef BaseBlock base_class_t; -	}; - -	template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value> -	class ParamValue : public NAME_VALUE_LOOKUP -	{ -	public: -		typedef const T&							value_assignment_t; -		typedef T									value_t; -		typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK>	self_t; - -		ParamValue(): mValue() {} -		ParamValue(value_assignment_t other) : mValue(other) {} - -		void setValue(value_assignment_t val) -		{ -			mValue = val; -		} - -		value_assignment_t getValue() const -		{ -			return mValue; -		} - -		T& getValue() -		{ -			return mValue; -		} - -		operator value_assignment_t() const -		{ -			return mValue; -		} - -		value_assignment_t operator()() const -		{ -			return mValue; -		} - -		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			*this = name; -		} - -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue)) -			{ -				setValueName(name); -			} - -			return *this; -		} - -	protected: -		T mValue; -	}; - -	template<typename T, typename NAME_VALUE_LOOKUP> -	class ParamValue<T, NAME_VALUE_LOOKUP, true>  -	:	public T, -		public NAME_VALUE_LOOKUP -	{ -	public: -		typedef const T&							value_assignment_t; -		typedef T									value_t; -		typedef ParamValue<T, NAME_VALUE_LOOKUP, true>	self_t; - -		ParamValue()  -		:	T(), -			mValidated(false) -		{} - -		ParamValue(value_assignment_t other) -		:	T(other), -			mValidated(false) -		{} - -		void setValue(value_assignment_t val) -		{ -			*this = val; -		} - -		value_assignment_t getValue() const -		{ -			return *this; -		} - -		T& getValue() -		{ -			return *this; +					(my_addr - (ptrdiff_t)getEnclosingBlockOffset()));  		} -		operator value_assignment_t() const +		U32 getEnclosingBlockOffset() const  		{ -			return *this; -		} -		 -		value_assignment_t operator()() const -		{ -			return *this; -		} - -		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			*this = name; -		} - -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			if (NAME_VALUE_LOOKUP::getValueFromName(name, *this)) -			{ -				setValueName(name); -			} - -			return *this; -		} - -	protected: -		mutable bool 	mValidated; // lazy validation flag -	}; - -	template<typename NAME_VALUE_LOOKUP> -	class ParamValue<std::string, NAME_VALUE_LOOKUP, false> -	: public NAME_VALUE_LOOKUP -	{ -	public: -		typedef const std::string&	value_assignment_t; -		typedef std::string			value_t; -		typedef ParamValue<std::string, NAME_VALUE_LOOKUP, false>	self_t; - -		ParamValue(): mValue() {} -		ParamValue(value_assignment_t other) : mValue(other) {} - -		void setValue(value_assignment_t val) -		{ -			if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue)) -			{ -				NAME_VALUE_LOOKUP::setValueName(val); -			} -			else -			{ -				mValue = val; -			} -		} - -		value_assignment_t getValue() const -		{ -			return mValue; +			return ((U32)mEnclosingBlockOffsetHigh << 16) | (U32)mEnclosingBlockOffsetLow;  		} -		std::string& getValue() -		{ -			return mValue; -		} - -		operator value_assignment_t() const -		{ -			return mValue; -		} +	private: +		friend class BaseBlock; -		value_assignment_t operator()() const -		{ -			return mValue; -		} +		//24 bits for member offset field and 1 bit for provided flag +		U16		mEnclosingBlockOffsetLow; +		U8		mEnclosingBlockOffsetHigh:7; +		U8		mIsProvided:1; -	protected: -		std::string mValue;  	}; -  	template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >  	struct ParamIterator  	{ -		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator		const_iterator; -		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator			iterator; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::const_iterator	const_iterator; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::iterator			iterator;  	}; -	// specialize for custom parsing/decomposition of specific classes -	// e.g. TypedParam<LLRect> has left, top, right, bottom, etc... +	// wrapper for parameter with a known type +	// specialized to handle 4 cases: +	// simple "scalar" value +	// parameter that is itself a block +	// multiple scalar values, stored in a vector +	// multiple blocks, stored in a vector  	template<typename	T,  			typename	NAME_VALUE_LOOKUP = TypeValues<T>,  			bool		HAS_MULTIPLE_VALUES = false, -			bool		VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> +			typename	VALUE_IS_BLOCK = typename IsBlock<ParamValue<typename LLTypeTags::Sorted<T>::value_t> >::value_t>  	class TypedParam   	:	public Param,  -		public ParamValue<T, NAME_VALUE_LOOKUP> +		public NAME_VALUE_LOOKUP::type_value_t  	{ +	protected: +		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>	self_t; +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>						param_value_t; +		typedef typename param_value_t::default_value_t									default_value_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t								named_value_t;  	public: -		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>		self_t; -		typedef ParamValue<T, NAME_VALUE_LOOKUP>											param_value_t; -		typedef typename param_value_t::value_assignment_t				value_assignment_t; -		typedef NAME_VALUE_LOOKUP															name_value_lookup_t; +		typedef typename param_value_t::value_t											value_t; -		using param_value_t::operator(); +		using named_value_t::operator(); -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  -		:	Param(block_descriptor.mCurrentBlockPtr) +		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) +		:	Param(block_descriptor.mCurrentBlockPtr), +			named_value_t(value)  		{  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ - 				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name);  			} - -			setValue(value);  		}   		bool isProvided() const { return Param::anyProvided(); } -		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) +		static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{   			self_t& typed_param = static_cast<self_t&>(param);  			// no further names in stack, attempt to parse value now @@ -858,14 +976,15 @@ namespace LLInitParam  				}  				// try to parse a known named value -				if(name_value_lookup_t::valueNamesExist()) +				if(named_value_t::valueNamesExist())  				{  					// try to parse a known named value  					std::string name;  					if (parser.readValue(name))  					{  						// try to parse a per type named value -						if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + +						if (named_value_t::getValueFromName(name, typed_param.getValue()))  						{  							typed_param.setValueName(name);  							typed_param.setProvided(); @@ -905,7 +1024,9 @@ namespace LLInitParam  				if (!parser.writeValue(typed_param.getValue(), name_stack))   				{  					std::string calculated_key = typed_param.calcValueName(typed_param.getValue()); -					if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)) +					if (calculated_key.size()  +						&& (!diff_param  +							|| !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)))  					{  						parser.writeValue(calculated_key, name_stack);  					} @@ -918,22 +1039,23 @@ namespace LLInitParam  			// tell parser about our actual type  			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);  			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) -			if (name_value_lookup_t::getPossibleValues()) +			if (named_value_t::getPossibleValues())  			{ -				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());  			}  		} -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const value_t& val, bool flag_as_provided = true)  		{ -			param_value_t::clearValueName(); +			named_value_t::clearValueName();  			setValue(val);  			setProvided(flag_as_provided);  		} -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) +		self_t& operator =(const typename named_value_t::name_t& name)  		{ -			return static_cast<self_t&>(param_value_t::operator =(name)); +			named_value_t::assignNamedValue(name); +			return *this;  		}  	protected: @@ -958,41 +1080,47 @@ namespace LLInitParam  			}  			return false;  		} +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func, +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	};  	// parameter that is a block  	template <typename T, typename NAME_VALUE_LOOKUP> -	class TypedParam<T, NAME_VALUE_LOOKUP, false, true>  +	class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>   	:	public Param, -		public ParamValue<T, NAME_VALUE_LOOKUP> +		public NAME_VALUE_LOOKUP::type_value_t  	{ +	protected: +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>	param_value_t; +		typedef typename param_value_t::default_value_t				default_value_t; +		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>	self_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t			named_value_t;  	public: -		typedef ParamValue<T, NAME_VALUE_LOOKUP>				param_value_t; -		typedef typename param_value_t::value_assignment_t		value_assignment_t; -		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true>	self_t; -		typedef NAME_VALUE_LOOKUP								name_value_lookup_t; +		using named_value_t::operator(); +		typedef typename param_value_t::value_t						value_t; -		using param_value_t::operator(); - -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) +		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  		:	Param(block_descriptor.mCurrentBlockPtr), -			param_value_t(value) +			named_value_t(value)  		{  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func,  -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name);  			}  		} -		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) +		static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{   			self_t& typed_param = static_cast<self_t&>(param);  			// attempt to parse block... @@ -1003,14 +1131,14 @@ namespace LLInitParam  				return true;  			} -			if(name_value_lookup_t::valueNamesExist()) +			if(named_value_t::valueNamesExist())  			{  				// try to parse a known named value  				std::string name;  				if (parser.readValue(name))  				{  					// try to parse a per type named value -					if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) +					if (named_value_t::getValueFromName(name, typed_param.getValue()))  					{  						typed_param.setValueName(name);  						typed_param.setProvided(); @@ -1035,9 +1163,9 @@ namespace LLInitParam  			std::string key = typed_param.getValueName();  			if (!key.empty())  			{ -				if (!parser.writeValue(key, name_stack)) +				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))  				{ -					return; +					parser.writeValue(key, name_stack);  				}  			}  			else @@ -1048,8 +1176,16 @@ namespace LLInitParam  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{ -			// I am a param that is also a block, so just recurse into my contents  			const self_t& typed_param = static_cast<const self_t&>(param); + +			// tell parser about our actual type +			parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); +			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) +			if (named_value_t::getPossibleValues()) +			{ +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); +			} +  			typed_param.inspectBlock(parser, name_stack, min_count, max_count);  		} @@ -1067,32 +1203,34 @@ namespace LLInitParam  		}  		// assign block contents to this param-that-is-a-block -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const value_t& val, bool flag_as_provided = true)  		{  			setValue(val); -			param_value_t::clearValueName(); +			named_value_t::clearValueName();  			// force revalidation of block  			// next call to isProvided() will update provision status based on validity  			param_value_t::mValidated = false;  			setProvided(flag_as_provided);  		} -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) +		self_t& operator =(const typename named_value_t::name_t& name)  		{ -			return static_cast<self_t&>(param_value_t::operator =(name)); +			named_value_t::assignNamedValue(name); +			return *this;  		}  		// propagate changed status up to enclosing block  		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)  		{   			param_value_t::paramChanged(changed_param, user_provided); +  			if (user_provided)  			{  				// a child param has been explicitly changed  				// so *some* aspect of this block is now provided  				param_value_t::mValidated = false;  				setProvided(); -				param_value_t::clearValueName(); +				named_value_t::clearValueName();  			}  			else  			{ @@ -1116,7 +1254,7 @@ namespace LLInitParam  			if (src_typed_param.anyProvided())  			{ -				if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite)) +				if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::getBlockDescriptor(), src_typed_param, overwrite))  				{  					dst_typed_param.clearValueName();  					dst_typed_param.setProvided(true); @@ -1125,49 +1263,65 @@ namespace LLInitParam  			}  			return false;  		} + +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func,  +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	}; -	// container of non-block parameters +	// list of non-block parameters  	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> -	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>  +	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK>   	:	public Param  	{ +	protected: +		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK>		self_t; +		typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t>	param_value_t; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t>	container_t; +		typedef container_t														default_value_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t						named_value_t; +		  	public: -		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>		self_t; -		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>					param_value_t; -		typedef typename std::vector<param_value_t>							container_t; -		typedef const container_t&											value_assignment_t; -  		typedef typename param_value_t::value_t								value_t; -		typedef NAME_VALUE_LOOKUP											name_value_lookup_t; -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  +		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  		:	Param(block_descriptor.mCurrentBlockPtr)  		{  			std::copy(value.begin(), value.end(), std::back_inserter(mValues));  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name); +  			}  		}   		bool isProvided() const { return Param::anyProvided(); } -		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) +		static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{  +			Parser::name_stack_range_t new_name_stack_range(name_stack_range);  			self_t& typed_param = static_cast<self_t&>(param);  			value_t value; + +			// pop first element if empty string +			if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) +			{ +				++new_name_stack_range.first; +			} +  			// no further names in stack, attempt to parse value now -			if (name_stack_range.first == name_stack_range.second) +			if (new_name_stack_range.first == new_name_stack_range.second)  			{  				// attempt to read value directly  				if (parser.readValue(value)) @@ -1177,14 +1331,14 @@ namespace LLInitParam  				}  				// try to parse a known named value -				if(name_value_lookup_t::valueNamesExist()) +				if(named_value_t::valueNamesExist())  				{  					// try to parse a known named value  					std::string name;  					if (parser.readValue(name))  					{  						// try to parse a per type named value -						if (name_value_lookup_t::getValueFromName(name, value)) +						if (named_value_t::getValueFromName(name, value))  						{  							typed_param.add(value);  							typed_param.mValues.back().setValueName(name); @@ -1200,14 +1354,14 @@ namespace LLInitParam  		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)  		{  			const self_t& typed_param = static_cast<const self_t&>(param); -			if (!typed_param.isProvided() || name_stack.empty()) return; +			if (!typed_param.isProvided()) return;  			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();  				it != end_it;  				++it)  			{  				std::string key = it->getValueName(); -				name_stack.back().second = true; +				name_stack.push_back(std::make_pair(std::string(), true));  				if(key.empty())  				// not parsed via name values, write out value directly @@ -1229,19 +1383,21 @@ namespace LLInitParam  						break;  					}  				} + +				name_stack.pop_back();  			}  		}  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{  			parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL); -			if (name_value_lookup_t::getPossibleValues()) +			if (named_value_t::getPossibleValues())  			{ -				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());  			}  		} -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const container_t& val, bool flag_as_provided = true)  		{  			mValues = val;  			setProvided(flag_as_provided); @@ -1249,26 +1405,24 @@ namespace LLInitParam  		param_value_t& add()  		{ -			mValues.push_back(param_value_t(value_t())); +			mValues.push_back(value_t());  			Param::setProvided();  			return mValues.back();  		}  		self_t& add(const value_t& item)  		{ -			param_value_t param_value; -			param_value.setValue(item); -			mValues.push_back(param_value); +			mValues.push_back(item);  			setProvided();  			return *this;  		} -		self_t& add(const typename name_value_lookup_t::name_t& name) +		self_t& add(const typename named_value_t::name_t& name)  		{  			value_t value;  			// try to parse a per type named value -			if (name_value_lookup_t::getValueFromName(name, value)) +			if (named_value_t::getValueFromName(name, value))  			{  				add(value);  				mValues.back().setValueName(name); @@ -1278,9 +1432,9 @@ namespace LLInitParam  		}  		// implicit conversion -		operator value_assignment_t() const { return mValues; }  +		operator const container_t&() const { return mValues; }   		// explicit conversion		 -		value_assignment_t operator()() const { return mValues; } +		const container_t& operator()() const { return mValues; }  		typedef typename container_t::iterator iterator;  		typedef typename container_t::const_iterator const_iterator; @@ -1321,72 +1475,97 @@ namespace LLInitParam  		}  		container_t		mValues; + +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func, +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	}; -	// container of block parameters +	// list of block parameters  	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> -	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>  +	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>   	:	public Param  	{ +	protected: +		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>		self_t; +		typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t>	param_value_t; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t>	container_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t						named_value_t; +		typedef container_t														default_value_t; +		typedef typename container_t::iterator									iterator; +		typedef typename container_t::const_iterator							const_iterator;  	public: -		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>	self_t; -		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>				param_value_t; -		typedef typename std::vector<param_value_t>						container_t; -		typedef const container_t&										value_assignment_t;  		typedef typename param_value_t::value_t							value_t; -		typedef NAME_VALUE_LOOKUP										name_value_lookup_t; -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  +		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  		:	Param(block_descriptor.mCurrentBlockPtr)  		{  			std::copy(value.begin(), value.end(), back_inserter(mValues));  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name);  			}  		}   		bool isProvided() const { return Param::anyProvided(); } -		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)  +		static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)   		{  +			Parser::name_stack_range_t new_name_stack_range(name_stack_range);  			self_t& typed_param = static_cast<self_t&>(param);  			bool new_value = false; +			bool new_array_value = false; -			if (new_name || typed_param.mValues.empty()) +			// pop first element if empty string +			if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) +			{ +				new_array_value = new_name_stack_range.first->second; +				++new_name_stack_range.first; +			} + +			if (new_name || new_array_value || typed_param.mValues.empty())  			{  				new_value = true;  				typed_param.mValues.push_back(value_t());  			} -  			param_value_t& value = typed_param.mValues.back();  			// attempt to parse block... -			if(value.deserializeBlock(parser, name_stack_range, new_name)) +			if(value.deserializeBlock(parser, new_name_stack_range, new_name))  			{  				typed_param.setProvided(); +				if (new_array_value) +				{ +					name_stack_range.first->second = false; +				}  				return true;  			} -			else if(name_value_lookup_t::valueNamesExist()) +			else if(named_value_t::valueNamesExist())  			{  				// try to parse a known named value  				std::string name;  				if (parser.readValue(name))  				{  					// try to parse a per type named value -					if (name_value_lookup_t::getValueFromName(name, value.getValue())) +					if (named_value_t::getValueFromName(name, value.getValue()))  					{  						typed_param.mValues.back().setValueName(name);  						typed_param.setProvided(); +						if (new_array_value) +						{ +							name_stack_range.first->second = false; +						}  						return true;  					} @@ -1404,13 +1583,13 @@ namespace LLInitParam  		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)  		{  			const self_t& typed_param = static_cast<const self_t&>(param); -			if (!typed_param.isProvided() || name_stack.empty()) return; +			if (!typed_param.isProvided()) return;  			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();  				it != end_it;  				++it)  			{ -				name_stack.back().second = true; +				name_stack.push_back(std::make_pair(std::string(), true));  				std::string key = it->getValueName();  				if (!key.empty()) @@ -1423,16 +1602,27 @@ namespace LLInitParam  				{  					it->serializeBlock(parser, name_stack, NULL);  				} + +				name_stack.pop_back();  			}  		}  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{ -			// I am a vector of blocks, so describe my contents recursively -			param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count); +			const param_value_t& value_param = param_value_t(value_t()); + +			// tell parser about our actual type +			parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); +			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) +			if (named_value_t::getPossibleValues()) +			{ +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); +		} + +			value_param.inspectBlock(parser, name_stack, min_count, max_count);  		} -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const container_t& val, bool flag_as_provided = true)  		{  			mValues = val;  			setProvided(flag_as_provided); @@ -1452,12 +1642,12 @@ namespace LLInitParam  			return *this;  		} -		self_t& add(const typename name_value_lookup_t::name_t& name) +		self_t& add(const typename named_value_t::name_t& name)  		{  			value_t value;  			// try to parse a per type named value -			if (name_value_lookup_t::getValueFromName(name, value)) +			if (named_value_t::getValueFromName(name, value))  			{  				add(value);  				mValues.back().setValueName(name); @@ -1466,12 +1656,10 @@ namespace LLInitParam  		}  		// implicit conversion -		operator value_assignment_t() const { return mValues; }  +		operator const container_t&() const { return mValues; }   		// explicit conversion -		value_assignment_t operator()() const { return mValues; } +		const container_t& operator()() const { return mValues; } -		typedef typename container_t::iterator iterator; -		typedef typename container_t::const_iterator const_iterator;  		iterator begin() { return mValues.begin(); }  		iterator end() { return mValues.end(); }  		const_iterator begin() const { return mValues.begin(); } @@ -1518,6 +1706,20 @@ namespace LLInitParam  		}  		container_t			mValues; + +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func, +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	};  	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> @@ -1532,13 +1734,13 @@ namespace LLInitParam  		// take all provided params from other and apply to self  		bool overwriteFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);  		}  		// take all provided params that are not already provided, and apply to self  		bool fillFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);  		}  		bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) @@ -1556,7 +1758,7 @@ namespace LLInitParam  		bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite)  		{  			mCurChoice = other.mCurChoice; -			return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite); +			return base_block_t::mergeBlock(getBlockDescriptor(), other, overwrite);  		}  		// clear out old choice when param has changed @@ -1577,38 +1779,38 @@ namespace LLInitParam  			base_block_t::paramChanged(changed_param, user_provided);  		} -		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } -		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } +		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } +		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }  	protected:  		ChoiceBlock()  		:	mCurChoice(0)  		{ -			BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); +			BaseBlock::init(getBlockDescriptor(), base_block_t::getBlockDescriptor(), sizeof(DERIVED_BLOCK));  		}  		// Alternatives are mutually exclusive wrt other Alternatives in the same block.    		// One alternative in a block will always have isChosen() == true.  		// At most one alternative in a block will have isProvided() == true. -		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{ +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>	super_t; +			typedef typename super_t::value_t				value_t; +			typedef typename super_t::default_value_t		default_value_t; +  		public:  			friend class ChoiceBlock<DERIVED_BLOCK>; -			typedef Alternative<T, NAME_VALUE_LOOKUP>									self_t; -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t; -			typedef typename super_t::value_assignment_t								value_assignment_t; -  			using super_t::operator =; -			explicit Alternative(const char* name = "", value_assignment_t val = defaultValue<T>()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), +			explicit Alternative(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1),  				mOriginalValue(val)  			{  				// assign initial choice to first declared option -				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); -				if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) +				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr); +				if (LL_UNLIKELY(DERIVED_BLOCK::getBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))  				{  					if(blockp->mCurChoice == 0)  					{ @@ -1622,27 +1824,27 @@ namespace LLInitParam  				static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true);  			} -			void chooseAs(value_assignment_t val) +			void chooseAs(const value_t& val)  			{  				super_t::set(val);  			} -			void operator =(value_assignment_t val) +			void operator =(const value_t& val)  			{  				super_t::set(val);  			} -			void operator()(typename super_t::value_assignment_t val)  +			void operator()(const value_t& val)   			{   				super_t::set(val);  			} -			operator value_assignment_t() const  +			operator const value_t&() const   			{  				return (*this)();  			}  -			value_assignment_t operator()() const  +			const value_t& operator()() const   			{   				if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)  				{ @@ -1657,11 +1859,11 @@ namespace LLInitParam  			}  		private: -			T			mOriginalValue; +			default_value_t mOriginalValue;  		}; -	protected: -		static BlockDescriptor& selfBlockDescriptor() +	public: +		static BlockDescriptor& getBlockDescriptor()  		{  			static BlockDescriptor sBlockDescriptor;  			return sBlockDescriptor; @@ -1681,6 +1883,8 @@ namespace LLInitParam  	:	public BASE_BLOCK  	{  		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	self_t; + +	protected:  		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	block_t;  	public: @@ -1689,80 +1893,82 @@ namespace LLInitParam  		// take all provided params from other and apply to self  		bool overwriteFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);  		}  		// take all provided params that are not already provided, and apply to self  		bool fillFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);  		} -		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } -		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } +		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } +		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }  	protected:  		Block()  		{  			//#pragma message("Parsing LLInitParam::Block") -			BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); +			BaseBlock::init(getBlockDescriptor(), BASE_BLOCK::getBlockDescriptor(), sizeof(DERIVED_BLOCK));  		}  		//  		// Nested classes for declaring parameters  		// -		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{ -		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t; -			typedef typename super_t::value_assignment_t								value_assignment_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>		super_t; +			typedef typename super_t::value_t					value_t; +			typedef typename super_t::default_value_t			default_value_t; +		public:  			using super_t::operator();  			using super_t::operator =; -			explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) +			explicit Optional(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1)  			{  				//#pragma message("Parsing LLInitParam::Block::Optional")  			} -			Optional& operator =(value_assignment_t val) +			Optional& operator =(const value_t& val)  			{  				set(val);  				return *this;  			} -			DERIVED_BLOCK& operator()(value_assignment_t val) +			DERIVED_BLOCK& operator()(const value_t& val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());  			}  		}; -		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{ -		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>		super_t;  			typedef Mandatory<T, NAME_VALUE_LOOKUP>										self_t; -			typedef typename super_t::value_assignment_t								value_assignment_t; +			typedef typename super_t::value_t					value_t; +			typedef typename super_t::default_value_t			default_value_t; +		public:  			using super_t::operator();  			using super_t::operator =;  			// mandatory parameters require a name to be parseable -			explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1) +			explicit Mandatory(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1)  			{} -			Mandatory& operator =(value_assignment_t val) +			Mandatory& operator =(const value_t& val)  			{  				set(val);  				return *this;  			} -			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) +			DERIVED_BLOCK& operator()(const value_t& val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1776,28 +1982,29 @@ namespace LLInitParam  		}; -		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>  		{ -		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>	super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, true>	super_t;  			typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP>							self_t;  			typedef typename super_t::container_t									container_t; -			typedef typename super_t::value_assignment_t							value_assignment_t; +			typedef typename super_t::value_t				value_t; + +		public:  			typedef typename super_t::iterator										iterator;  			typedef typename super_t::const_iterator								const_iterator;  			explicit Multiple(const char* name = "") -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)  			{} -			Multiple& operator =(value_assignment_t val) +			Multiple& operator =(const container_t& val)  			{  				set(val);  				return *this;  			} -			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) +			DERIVED_BLOCK& operator()(const container_t& val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1810,13 +2017,15 @@ namespace LLInitParam  			}  		}; -		class Deprecated : public Param +		// can appear in data files, but will ignored during parsing +		// cannot read or write in code +		class Ignored : public Param  		{  		public: -			explicit Deprecated(const char* name) -			:	Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) +			explicit Ignored(const char* name) +			:	Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr)  			{ -				BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); +				BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor();  				if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  				{  					ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( @@ -1827,11 +2036,11 @@ namespace LLInitParam  													NULL,  													NULL,   													0, S32_MAX)); -					BaseBlock::addParam(block_descriptor, param_descriptor, name); +					block_descriptor.addParam(param_descriptor, name);  				}  			} -			static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) +			static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)  			{  				if (name_stack_range.first == name_stack_range.second)  				{ @@ -1844,19 +2053,46 @@ namespace LLInitParam  			}  		}; -		// different semantics for documentation purposes, but functionally identical -		typedef Deprecated Ignored; +		// can appear in data files, or be written to in code, but data will be ignored +		// cannot be read in code +		class Deprecated : public Ignored +		{ +		public: +			explicit Deprecated(const char* name) : Ignored(name) {} -	protected: -		static BlockDescriptor& selfBlockDescriptor() +			// dummy writer interfaces +			template<typename T> +			Deprecated& operator =(const T& val) +			{ +				// do nothing +				return *this; +			} + +			template<typename T> +			DERIVED_BLOCK& operator()(const T& val) +			{ +				// do nothing +				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); +			} + +			template<typename T> +			void set(const T& val, bool flag_as_provided = true) +			{ +				// do nothing +			} +		}; + +	public: +		static BlockDescriptor& getBlockDescriptor()  		{  			static BlockDescriptor sBlockDescriptor;  			return sBlockDescriptor;  		} -		template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block> +	protected: +		template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, typename is_block>  		void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param,  -			typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value) +			const typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_t& value)  		{  			if (!param.isProvided())  			{ @@ -1866,204 +2102,420 @@ namespace LLInitParam  	}; -	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> -	class BatchBlock -	:	public Block<DERIVED_BLOCK, BASE_BLOCK> +	template<typename T, typename BLOCK_T> +	struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::IS_A_BLOCK>, BLOCK_T >, void> +	{ +		typedef IS_A_BLOCK value_t; +	}; + +	template<typename T, typename BLOCK_T> +	struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::NOT_A_BLOCK>, BLOCK_T >, void> +	{ +		typedef NOT_BLOCK value_t; +	}; + +	template<typename T, typename BLOCK_IDENTIFIER> +	struct IsBlock<ParamValue<BaseBlock::Atomic<T>, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER> +	{ +		typedef typename IsBlock<T>::value_t value_t; +	}; + +	template<typename T, typename BLOCK_IDENTIFIER> +	struct IsBlock<ParamValue<BaseBlock::Sequential<T>, typename IsBlock<BaseBlock::Sequential<T> >::value_t >, BLOCK_IDENTIFIER> +	{ +		typedef typename IsBlock<T>::value_t value_t; +	}; + + +	template<typename T> +	struct InnerMostType +	{ +		typedef T value_t; +	}; + +	template<typename T> +	struct InnerMostType<ParamValue<T, NOT_BLOCK> >  	{ +		typedef typename InnerMostType<T>::value_t value_t; +	}; + +	template<typename T> +	struct InnerMostType<ParamValue<T, IS_A_BLOCK> > +	{ +		typedef typename InnerMostType<T>::value_t value_t; +	}; + +	template<typename T, typename BLOCK_T> +	class ParamValue <BaseBlock::Atomic<T>, BLOCK_T> +	{ +		typedef ParamValue <BaseBlock::Atomic<T>, BLOCK_T> self_t; +  	public: -		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> self_t; -		typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t; +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef T									default_value_t; + +		ParamValue() +		:	mValue(), +			mValidated(false) +		{} -		BatchBlock() +		ParamValue(const default_value_t& value) +		:	mValue(value), +			mValidated(false)  		{} -		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) +		void setValue(const value_t& val) +		{ +			mValue.setValue(val); +		} + +		const value_t& getValue() const +		{ +			return mValue.getValue(); +		} + +		value_t& getValue() +		{ +			return mValue.getValue(); +		} + +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{  			if (new_name)  			{ -				// reset block -				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); +				resetToDefault();  			} -			return super_t::deserializeBlock(p, name_stack_range, new_name); +			return mValue.deserializeBlock(p, name_stack_range, new_name);  		} -		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) +		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const  		{ -			if (overwrite) +			const BaseBlock* base_block = diff_block +				? &(diff_block->mValue) +				: NULL; +			mValue.serializeBlock(p, name_stack, base_block); +		} + +		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const +		{ +			return mValue.inspectBlock(p, name_stack, min_count, max_count); +		} + +		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) +		{ +			if ((overwrite && source_provided) // new values coming in on top or... +				|| (!overwrite && !dst_provided)) // values being pushed under with nothing already there  			{ -				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); -				// merge individual parameters into destination -				return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite); +				// clear away what is there and take the new stuff as a whole +				resetToDefault(); +				return mValue.mergeBlock(block_data, source.getValue(), overwrite);  			} -			return false; +			 + +			return mValue.mergeBlock(block_data, source.getValue(), overwrite);  		} -	protected: -		static const DERIVED_BLOCK& defaultBatchValue() + +		bool validateBlock(bool emit_errors = true) const +		{ +			return mValue.validateBlock(emit_errors); +		} + +		static BlockDescriptor& getBlockDescriptor() +		{ +			return value_t::getBlockDescriptor(); +		} + + +		mutable bool 	mValidated; // lazy validation flag + +	private: +		void resetToDefault()  		{ -			static DERIVED_BLOCK default_value; -			return default_value; +			static T default_value; +			mValue = default_value;  		} + +		T	mValue;  	}; -	// FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class -	// and not the derived class with the actual params -	template<typename DERIVED_BLOCK, -			typename BASE_BLOCK, -			typename NAME_VALUE_LOOKUP> -	class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>, -					NAME_VALUE_LOOKUP, -					true> -	:	public NAME_VALUE_LOOKUP, -		protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK> +	template<typename T> +	class ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK>  	{ +		typedef ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK> self_t; +  	public: -		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t; -		typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>&	value_assignment_t; -		typedef block_t value_t; +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef T									default_value_t;  		ParamValue() -		:	block_t(), +		:	mValue(),  			mValidated(false) -		{} +		{ +			mCurParam = getBlockDescriptor().mAllParams.begin(); +		} -		ParamValue(value_assignment_t other) -		:	block_t(other), +		ParamValue(const default_value_t& value) +		:	mValue(value),  			mValidated(false)  		{ +			mCurParam = getBlockDescriptor().mAllParams.begin();  		} -		void setValue(value_assignment_t val) +		void setValue(const value_t& val)  		{ -			*this = val; +			mValue.setValue(val);  		} -		value_assignment_t getValue() const +		const value_t& getValue() const  		{ -			return *this; +			return mValue.getValue();  		} -		BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& getValue() +		value_t& getValue()  		{ -			return *this; +			return mValue.getValue();  		} -		operator value_assignment_t() const +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{ -			return *this; +			if (new_name) +			{ +				mCurParam = getBlockDescriptor().mAllParams.begin(); +			} +			if (name_stack_range.first == name_stack_range.second  +				&& mCurParam != getBlockDescriptor().mAllParams.end()) +			{ +				// deserialize to mCurParam +				ParamDescriptor& pd = *(*mCurParam); +				ParamDescriptor::deserialize_func_t deserialize_func = pd.mDeserializeFunc; +				Param* paramp = mValue.getParamFromHandle(pd.mParamHandle); + +				if (deserialize_func  +					&& paramp  +					&& deserialize_func(*paramp, p, name_stack_range, new_name)) +				{ +					++mCurParam; +					return true; +				} +				else +				{ +					return false; +				} +			} +			else +			{ +				return mValue.deserializeBlock(p, name_stack_range, new_name); +			}  		} -		value_assignment_t operator()() const +		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const  		{ -			return *this; +			const BaseBlock* base_block = diff_block +				? &(diff_block->mValue) +				: NULL; +			mValue.serializeBlock(p, name_stack, base_block); +		} + +		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const +		{ +			return mValue.inspectBlock(p, name_stack, min_count, max_count); +		} + +		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) +		{ +			return mValue.mergeBlock(block_data, source.getValue(), overwrite); +		} + +		bool validateBlock(bool emit_errors = true) const +		{ +			return mValue.validateBlock(emit_errors); +		} + +		static BlockDescriptor& getBlockDescriptor() +		{ +			return value_t::getBlockDescriptor();  		} -	protected:  		mutable bool 	mValidated; // lazy validation flag + +	private: + +		BlockDescriptor::all_params_list_t::iterator	mCurParam; +		T												mValue;  	}; -	template<typename T, bool IS_BLOCK> -	class ParamValue <BaseBlock::Lazy<T>, -					TypeValues<T>, -					IS_BLOCK> -	:	public IsBlock<T>::base_class_t +	template<typename T> +	class ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> +	: public T  	{ +		typedef ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> self_t; +  	public: -		typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<T>, false> self_t; -		typedef const T& value_assignment_t; -		typedef T value_t; +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef T									default_value_t; + +		ParamValue() +		:	T(), +			mValidated(false) +		{} + +		ParamValue(const default_value_t& value) +		:	T(value.getValue()), +			mValidated(false) +		{} + +		mutable bool 	mValidated; // lazy validation flag +	}; + +	template<typename T, typename BLOCK_T> +	class ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T>  +	{ +		typedef ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> self_t; + +	public: +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef LazyValue<T>						default_value_t;  		ParamValue()  		:	mValue(),  			mValidated(false)  		{} -		ParamValue(value_assignment_t other) +		ParamValue(const default_value_t& other)  		:	mValue(other),  			mValidated(false)  		{} -		void setValue(value_assignment_t val) +		ParamValue(const T& value) +		:	mValue(value), +			mValidated(false) +		{} + +		void setValue(const value_t& val)  		{  			mValue.set(val);  		} -		value_assignment_t getValue() const +		const value_t& getValue() const  		{ -			return mValue.get(); +			return mValue.get().getValue();  		} -		T& getValue() +		value_t& getValue() +		{ +			return mValue.get().getValue(); +		} + +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name) +		{ +			return mValue.get().deserializeBlock(p, name_stack_range, new_name); +		} + +		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const  		{ -			return mValue.get(); +			if (mValue.empty()) return; +			 +			const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty()) +											? &(diff_block->mValue.get().getValue()) +											: NULL; +			mValue.get().serializeBlock(p, name_stack, base_block);  		} -		operator value_assignment_t() const +		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const  		{ -			return mValue.get(); +			return mValue.get().inspectBlock(p, name_stack, min_count, max_count);  		} -		value_assignment_t operator()() const +		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)  		{ -			return mValue.get(); +			return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite);  		} -		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) +		bool validateBlock(bool emit_errors = true) const  		{ -			return mValue.get().deserializeBlock(p, name_stack_range, new_name); +			return mValue.empty() || mValue.get().validateBlock(emit_errors);  		} -		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const +		static BlockDescriptor& getBlockDescriptor()  		{ -			if (mValue.empty()) return; +			return value_t::getBlockDescriptor(); +		} + +		mutable bool 	mValidated; // lazy validation flag + +	private: +		LazyValue<T>	mValue; +	}; + +	template<typename T, typename BLOCK_T> +	class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> +		{ +		typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t; + +	public: +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef LazyValue<T>						default_value_t; + +		ParamValue() +		:	mValue(), +			mValidated(false) +		{} + +		ParamValue(const default_value_t& other) +		:	mValue(other), +			mValidated(false) +		{} + +		ParamValue(const T& value) +		:	mValue(value), +			mValidated(false) +		{} -			mValue.get().serializeBlock(p, name_stack, diff_block); +		void setValue(const value_t& val) +		{ +			mValue.set(val);  		} -		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const +		const value_t& getValue() const  		{ -			if (mValue.empty()) return false; +			return mValue.get().getValue(); +		} -			return mValue.get().inspectBlock(p, name_stack, min_count, max_count); +		value_t& getValue() +		{ +			return mValue.get().getValue();  		} -	protected:  		mutable bool 	mValidated; // lazy validation flag  	private: -		BaseBlock::Lazy<T>	mValue; +		LazyValue<T>	mValue;  	};  	template <> -	class ParamValue <LLSD, -					TypeValues<LLSD>, -					false> -	:	public TypeValues<LLSD>, -		public BaseBlock +	class ParamValue <LLSD, NOT_BLOCK> +	:	public BaseBlock  	{  	public: -		typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t; -		typedef const LLSD&	value_assignment_t; +		typedef LLSD			value_t; +		typedef LLSD			default_value_t;  		ParamValue()  		:	mValidated(false)  		{} -		ParamValue(value_assignment_t other) +		ParamValue(const default_value_t& other)  		:	mValue(other),  			mValidated(false)  		{} -		void setValue(value_assignment_t val) { mValue = val; } +		void setValue(const value_t& val) { mValue = val; } -		value_assignment_t getValue() const { return mValue; } +		const value_t& getValue() const { return mValue; }  		LLSD& getValue() { return mValue; } -		operator value_assignment_t() const { return mValue; } -		value_assignment_t operator()() const { return mValue; } -		 -  		// block param interface -		LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); +		LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name);  		LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;  		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const  		{ @@ -2082,8 +2534,7 @@ namespace LLInitParam  	template<typename T>  	class CustomParamValue -	:	public Block<ParamValue<T, TypeValues<T> > >, -		public TypeValues<T> +	:	public Block<ParamValue<T> >  	{  	public:  		typedef enum e_value_age @@ -2093,20 +2544,21 @@ namespace LLInitParam  			BLOCK_AUTHORITATIVE		// mValue is derived from the block parameters, which are authoritative  		} EValueAge; -		typedef ParamValue<T, TypeValues<T> >	derived_t; -		typedef CustomParamValue<T>				self_t; -		typedef Block<derived_t>				block_t; -		typedef const T&						value_assignment_t; -		typedef T								value_t; +		typedef ParamValue<T>			derived_t; +		typedef CustomParamValue<T>		self_t; +		typedef Block<derived_t>		block_t; +		typedef T						default_value_t; +		typedef T						value_t; +		typedef void					baseblock_base_class_t; -		CustomParamValue(const T& value = T()) +		CustomParamValue(const default_value_t& value = T())  		:	mValue(value),  			mValueAge(VALUE_AUTHORITATIVE),  			mValidated(false)  		{} -		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name) +		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{  			derived_t& typed_param = static_cast<derived_t&>(*this);  			// try to parse direct value T @@ -2117,8 +2569,6 @@ namespace LLInitParam  					typed_param.mValueAge = VALUE_AUTHORITATIVE;  					typed_param.updateBlockFromValue(false); -					typed_param.clearValueName(); -  					return true;  				}  			} @@ -2132,18 +2582,8 @@ namespace LLInitParam  			const derived_t& typed_param = static_cast<const derived_t&>(*this);  			const derived_t* diff_param = static_cast<const derived_t*>(diff_block); -			std::string key = typed_param.getValueName(); - -			// first try to write out name of name/value pair -			if (!key.empty()) -			{ -				if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key)) -				{ -					parser.writeValue(key, name_stack); -				} -			}  			// then try to serialize value directly -			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue())) +			if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))              {  				if (!parser.writeValue(typed_param.getValue(), name_stack))  @@ -2173,19 +2613,6 @@ namespace LLInitParam  			}  		} -		bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const -		{ -			// first, inspect with actual type... -			parser.inspectValue<T>(name_stack, min_count, max_count, NULL); -			if (TypeValues<T>::getPossibleValues()) -			{ -				//...then inspect with possible string values... -				parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues()); -			} -			// then recursively inspect contents... -			return block_t::inspectBlock(parser, name_stack, min_count, max_count); -		} -  		bool validateBlock(bool emit_errors = true) const  		{  			if (mValueAge == VALUE_NEEDS_UPDATE) @@ -2193,7 +2620,6 @@ namespace LLInitParam  				if (block_t::validateBlock(emit_errors))  				{  					// clear stale keyword associated with old value -					TypeValues<T>::clearValueName();  					mValueAge = BLOCK_AUTHORITATIVE;  					static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();  					return true; @@ -2223,17 +2649,15 @@ namespace LLInitParam  			}  		} -		void setValue(value_assignment_t val) +		void setValue(const value_t& val)  		{ -			derived_t& typed_param = static_cast<derived_t&>(*this);  			// set param version number to be up to date, so we ignore block contents  			mValueAge = VALUE_AUTHORITATIVE;  			mValue = val; -			typed_param.clearValueName();  			static_cast<derived_t*>(this)->updateBlockFromValue(false);  		} -		value_assignment_t getValue() const +		const value_t& getValue() const  		{  			validateBlock(true);  			return mValue; @@ -2245,20 +2669,10 @@ namespace LLInitParam  			return mValue;  		} -		operator value_assignment_t() const -		{ -			return getValue(); -		} - -		value_assignment_t operator()() const -		{ -			return getValue(); -		} -  	protected:  		// use this from within updateValueFromBlock() to set the value without making it authoritative -		void updateValue(value_assignment_t value) +		void updateValue(const value_t& value)  		{  			mValue = value;  		} diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 403df08990..1eab270e3c 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -43,7 +43,7 @@   * semantics: one instance per process, rather than one instance per module as   * sometimes happens with data simply declared static.   */ -class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable +class LL_COMMON_API LLInstanceTrackerBase  {  protected:  	/// Get a process-unique void* pointer slot for the specified type_info @@ -210,6 +210,9 @@ protected:  	virtual const KEY& getKey() const { return mInstanceKey; }  private: +	LLInstanceTracker( const LLInstanceTracker& ); +	const LLInstanceTracker& operator=( const LLInstanceTracker& ); +  	void add_(KEY key)   	{   		mInstanceKey = key;  diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 8eb5d53f3f..32ae15435a 100644 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -27,6 +27,7 @@  #define LLREFCOUNT_H  #include <boost/noncopyable.hpp> +#include <boost/intrusive_ptr.hpp>  #define LL_REF_COUNT_DEBUG 0  #if LL_REF_COUNT_DEBUG @@ -86,4 +87,22 @@ private:  #endif  }; +/** + * intrusive pointer support + * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type + */ +namespace boost +{ +	inline void intrusive_ptr_add_ref(LLRefCount* p) +	{ +		p->ref(); +	} + +	inline void intrusive_ptr_release(LLRefCount* p) +	{ +		p->unref(); +	} +}; + +  #endif diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h index 36d7f7a44c..bb0d60247e 100644 --- a/indra/llcommon/llregistry.h +++ b/indra/llcommon/llregistry.h @@ -31,30 +31,16 @@  #include <boost/type_traits.hpp>  #include "llsingleton.h" -#include "lltypeinfolookup.h" +#include "llstl.h"  template <typename T> -class LLRegistryDefaultComparator +struct LLRegistryDefaultComparator  { -	bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; } -}; - -template <typename KEY, typename VALUE> -struct LLRegistryMapSelector -{ -    typedef std::map<KEY, VALUE> type; -}; - -template <typename VALUE> -struct LLRegistryMapSelector<std::type_info*, VALUE> -{ -    typedef LLTypeInfoLookup<VALUE> type; -}; - -template <typename VALUE> -struct LLRegistryMapSelector<const std::type_info*, VALUE> -{ -    typedef LLTypeInfoLookup<VALUE> type; +	bool operator()(const T& lhs, const T& rhs) const +	{ +		using std::less; +		return less<T>()(lhs, rhs); +	}  };  template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> > @@ -72,7 +58,7 @@ public:  	{  		friend class LLRegistry<KEY, VALUE, COMPARATOR>;  	public: -		typedef typename LLRegistryMapSelector<KEY, VALUE>::type registry_map_t; +		typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;  		bool add(ref_const_key_t key, ref_const_value_t value)  		{ @@ -321,6 +307,10 @@ public:  		virtual ~StaticRegistrar() {}  		StaticRegistrar(ref_const_key_t key, ref_const_value_t value)  		{ +			if (singleton_t::instance().exists(key)) +			{ +				llerrs << "Duplicate registry entry under key \"" << key << "\"" << llendl; +			}  			singleton_t::instance().mStaticScope->add(key, value);  		}  	}; diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index 0e29873bb0..9f4460a988 100644 --- a/indra/llcommon/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp @@ -223,10 +223,14 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:  	{  		bool new_traversal = it->second; -		LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first]; - -		if (child_sd->isArray()) +		LLSD* child_sd; +		if (it->first.empty())  		{ +			child_sd = sd_to_write; +			if (child_sd->isUndefined()) +			{ +				*child_sd = LLSD::emptyArray(); +			}  			if (new_traversal)  			{  				// write to new element at end @@ -240,22 +244,7 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:  		}  		else  		{ -			if (new_traversal  -				&& child_sd->isDefined()  -				&& !child_sd->isArray()) -			{ -				// copy child contents into first element of an array -				LLSD new_array = LLSD::emptyArray(); -				new_array.append(*child_sd); -				// assign array to slot that previously held the single value -				*child_sd = new_array; -				// return next element in that array -				sd_to_write = &((*child_sd)[1]); -			} -			else -			{ -				sd_to_write = child_sd; -			} +			sd_to_write = &(*sd_to_write)[it->first];  		}  		it->second = false;  	} @@ -283,8 +272,9 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI  			it != sd.endArray();  			++it)  		{ -			stack.back().second = true; +			stack.push_back(make_pair(std::string(), true));  			readSDValues(cb, *it, stack); +			stack.pop_back();  		}  	}  	else if (sd.isUndefined()) @@ -313,8 +303,14 @@ namespace LLInitParam  {  	// LLSD specialization  	// block param interface -	bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) +	bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack, bool new_name)  	{ +		if (name_stack.first == name_stack.second +			&& p.readValue<LLSD>(mValue)) +		{ +			return true; +		} +  		LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);  		LLSD::String string; @@ -328,15 +324,18 @@ namespace LLInitParam  	}  	//static -	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) +	void ParamValue<LLSD, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)  	{  		p.writeValue<LLSD::String>(sd.asString(), name_stack);  	} -	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const +	void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const  	{ -		// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) -		Parser::name_stack_t stack; -		LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack); +		// attempt to write LLSD out directly +		if (!p.writeValue<LLSD>(mValue, name_stack)) +		{ +			// otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) +			LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack); +		}  	}  } diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 8ad12c9a03..d3941e1bc9 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -33,6 +33,7 @@  #include <vector>  #include <set>  #include <deque> +#include <typeinfo>  // Use to compare the first element only of a pair  // e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t;  @@ -470,4 +471,54 @@ llbind2nd(const _Operation& __oper, const _Tp& __x)    return llbinder2nd<_Operation>(__oper, _Arg2_type(__x));  } +/** + * Compare std::type_info* pointers a la std::less. We break this out as a + * separate function for use in two different std::less specializations. + */ +inline +bool before(const std::type_info* lhs, const std::type_info* rhs) +{ +#if LL_LINUX && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) +    // If we're building on Linux with gcc, and it's either gcc 3.x or +    // 4.{0,1,2,3}, then we have to use a workaround. Note that we use gcc on +    // Mac too, and some people build with gcc on Windows (cygwin or mingw). +    // On Linux, different load modules may produce different type_info* +    // pointers for the same type. Have to compare name strings to get good +    // results. +    return strcmp(lhs->name(), rhs->name()) < 0; +#else  // not Linux, or gcc 4.4+ +    // Just use before(), as we normally would +    return lhs->before(*rhs); +#endif +} + +/** + * Specialize std::less<std::type_info*> to use std::type_info::before(). + * See MAINT-1175. It is NEVER a good idea to directly compare std::type_info* + * because, on Linux, you might get different std::type_info* pointers for the + * same type (from different load modules)! + */ +namespace std +{ +	template <> +	struct less<const std::type_info*>: +		public std::binary_function<const std::type_info*, const std::type_info*, bool> +	{ +		bool operator()(const std::type_info* lhs, const std::type_info* rhs) const +		{ +			return before(lhs, rhs); +		} +	}; + +	template <> +	struct less<std::type_info*>: +		public std::binary_function<std::type_info*, std::type_info*, bool> +	{ +		bool operator()(std::type_info* lhs, std::type_info* rhs) const +		{ +			return before(lhs, rhs); +		} +	}; +} // std +  #endif // LL_LLSTL_H diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index b52e70ab2e..cf39696b4f 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -30,6 +30,7 @@  #include "llapp.h"  #include "llapr.h"  #include "apr_thread_cond.h" +#include "boost/intrusive_ptr.hpp"  class LLThread;  class LLMutex; @@ -266,6 +267,22 @@ private:  	S32	mRef;   }; +/** + * intrusive pointer support for LLThreadSafeRefCount + * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type + */ +namespace boost +{ +	inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p)  +	{ +		p->ref(); +	} + +	inline void intrusive_ptr_release(LLThreadSafeRefCount* p)  +	{ +		p->unref();  +	} +};  //============================================================================  // Simple responder for self destructing callbacks diff --git a/indra/llcommon/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h index 7510cc12ed..0b6862444e 100644 --- a/indra/llcommon/lltypeinfolookup.h +++ b/indra/llcommon/lltypeinfolookup.h @@ -12,10 +12,50 @@  #if ! defined(LL_LLTYPEINFOLOOKUP_H)  #define LL_LLTYPEINFOLOOKUP_H -#include "llsortedvector.h" +#include <boost/unordered_map.hpp> +#include <boost/functional/hash.hpp> +#include <boost/optional.hpp> +#include <functional>               // std::binary_function  #include <typeinfo>  /** + * The following helper classes are based on the Boost.Unordered documentation: + * http://www.boost.org/doc/libs/1_45_0/doc/html/unordered/hash_equality.html + */ + +/** + * Compute hash for a string passed as const char* + */ +struct const_char_star_hash: public std::unary_function<const char*, std::size_t> +{ +    std::size_t operator()(const char* str) const +    { +        std::size_t seed = 0; +        for ( ; *str; ++str) +        { +            boost::hash_combine(seed, *str); +        } +        return seed; +    } +}; + +/** + * Compute equality for strings passed as const char* + * + * I (nat) suspect that this is where the default behavior breaks for the + * const char* values returned from std::type_info::name(). If you compare the + * two const char* pointer values, as a naive, unspecialized implementation + * will surely do, they'll compare unequal. + */ +struct const_char_star_equal: public std::binary_function<const char*, const char*, bool> +{ +    bool operator()(const char* lhs, const char* rhs) const +    { +        return strcmp(lhs, rhs) == 0; +    } +}; + +/**   * LLTypeInfoLookup is specifically designed for use cases for which you might   * consider std::map<std::type_info*, VALUE>. We have several such data   * structures in the viewer. The trouble with them is that at least on Linux, @@ -23,88 +63,55 @@   * different load modules will produce different std::type_info*.   * LLTypeInfoLookup contains a workaround to address this issue.   * - * Specifically, when we don't find the passed std::type_info*, - * LLTypeInfoLookup performs a linear search over registered entries to - * compare name() strings. Presuming that this succeeds, we cache the new - * (previously unrecognized) std::type_info* to speed future lookups. - * - * This worst-case fallback search (linear search with string comparison) - * should only happen the first time we look up a given type from a particular - * load module other than the one from which we initially registered types. - * (However, a lookup which wouldn't succeed anyway will always have - * worst-case performance.) This class is probably best used with less than a - * few dozen different types. + * The API deliberately diverges from std::map in several respects: + * * It avoids iterators, not only begin()/end() but also as return values + *   from insert() and find(). This bypasses transform_iterator overhead. + * * Since we literally use compile-time types as keys, the essential insert() + *   and find() methods accept the key type as a @em template parameter, + *   accepting and returning value_type as a normal runtime value. This is to + *   permit future optimization (e.g. compile-time type hashing) without + *   changing the API.   */  template <typename VALUE>  class LLTypeInfoLookup  { +    // Use this for our underlying implementation: lookup by +    // std::type_info::name() string. This is one of the rare cases in which I +    // dare use const char* directly, rather than std::string, because I'm +    // sure that every value returned by std::type_info::name() is static. +    // HOWEVER, specify our own hash + equality functors: naively comparing +    // distinct const char* values won't work. +    typedef boost::unordered_map<const char*, VALUE, +                                 const_char_star_hash, const_char_star_equal> impl_map_type; +  public: -    typedef LLTypeInfoLookup<VALUE> self; -    typedef LLSortedVector<const std::type_info*, VALUE> vector_type; -    typedef typename vector_type::key_type key_type; -    typedef typename vector_type::mapped_type mapped_type; -    typedef typename vector_type::value_type value_type; -    typedef typename vector_type::iterator iterator; -    typedef typename vector_type::const_iterator const_iterator; +    typedef VALUE value_type;      LLTypeInfoLookup() {} -    iterator begin() { return mVector.begin(); } -    iterator end()   { return mVector.end(); } -    const_iterator begin() const { return mVector.begin(); } -    const_iterator end()   const { return mVector.end(); } -    bool empty() const { return mVector.empty(); } -    std::size_t size() const { return mVector.size(); } - -    std::pair<iterator, bool> insert(const std::type_info* key, const VALUE& value) -    { -        return insert(value_type(key, value)); -    } - -    std::pair<iterator, bool> insert(const value_type& pair) -    { -        return mVector.insert(pair); -    } +    bool empty() const { return mMap.empty(); } +    std::size_t size() const { return mMap.size(); } -    // const find() forwards to non-const find(): this can alter mVector! -    const_iterator find(const std::type_info* key) const +    template <typename KEY> +    bool insert(const value_type& value)      { -        return const_cast<self*>(this)->find(key); +        // Obtain and store the std::type_info::name() string as the key. +        // Return just the bool from std::map::insert()'s return pair. +        return mMap.insert(typename impl_map_type::value_type(typeid(KEY).name(), value)).second;      } -    // non-const find() caches previously-unknown type_info* to speed future -    // lookups. -    iterator find(const std::type_info* key) +    template <typename KEY> +    boost::optional<value_type> find() const      { -        iterator found = mVector.find(key); -        if (found != mVector.end()) -        { -            // If LLSortedVector::find() found, great, we're done. -            return found; -        } -        // Here we didn't find the passed type_info*. On Linux, though, even -        // for the same type, typeid(sametype) produces a different type_info* -        // when used in different load modules. So the fact that we didn't -        // find the type_info* we seek doesn't mean this type isn't -        // registered. Scan for matching name() string. -        for (typename vector_type::iterator ti(mVector.begin()), tend(mVector.end()); -             ti != tend; ++ti) -        { -            if (std::string(ti->first->name()) == key->name()) -            { -                // This unrecognized 'key' is for the same type as ti->first. -                // To speed future lookups, insert a new entry that lets us -                // look up ti->second using this same 'key'. -                return insert(key, ti->second).first; -            } -        } -        // We simply have never seen a type with this type_info* from any load -        // module. -        return mVector.end(); +        // Use the std::type_info::name() string as the key. +        typename impl_map_type::const_iterator found = mMap.find(typeid(KEY).name()); +        if (found == mMap.end()) +            return boost::optional<value_type>(); +        return found->second;      }  private: -    vector_type mVector; +    impl_map_type mMap;  };  #endif /* ! defined(LL_LLTYPEINFOLOOKUP_H) */ diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 2038681905..bcc661a920 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@  const S32 LL_VERSION_MAJOR = 3;  const S32 LL_VERSION_MINOR = 4; -const S32 LL_VERSION_PATCH = 0; +const S32 LL_VERSION_PATCH = 1;  const S32 LL_VERSION_BUILD = 0;  const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h index 40b3364b36..efcbe76795 100644 --- a/indra/llcommon/stdenums.h +++ b/indra/llcommon/stdenums.h @@ -51,7 +51,8 @@ enum EDragAndDropType  	DAD_LINK			= 14,  	DAD_MESH            = 15,  	DAD_WIDGET          = 16, -	DAD_COUNT           = 17,   // number of types in this enum +	DAD_PERSON          = 17, +	DAD_COUNT           = 18,   // number of types in this enum  };  // Reasons for drags to be denied. diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index fbf23bc3f0..a80ae73dca 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -75,13 +75,15 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid,  	mUUID(uuid),  	mParentUUID(parent_uuid),  	mType(type), -	mName(name) +	mName(name), +	mCreationDate(0)  {  	correctInventoryName(mName);  }  LLInventoryObject::LLInventoryObject() : -	mType(LLAssetType::AT_NONE) +	mType(LLAssetType::AT_NONE), +	mCreationDate(0)  {  } @@ -275,6 +277,18 @@ void LLInventoryObject::correctInventoryName(std::string& name)  	LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN);  } +time_t LLInventoryObject::getCreationDate() const +{ +	return mCreationDate; +} + +void LLInventoryObject::setCreationDate(time_t creation_date_utc) +{ +	mCreationDate = creation_date_utc; +} + + +  ///----------------------------------------------------------------------------  /// Class LLInventoryItem @@ -297,9 +311,10 @@ LLInventoryItem::LLInventoryItem(const LLUUID& uuid,  	mDescription(desc),  	mSaleInfo(sale_info),  	mInventoryType(inv_type), -	mFlags(flags), -	mCreationDate(creation_date_utc) +	mFlags(flags)  { +	mCreationDate = creation_date_utc; +  	LLStringUtil::replaceNonstandardASCII(mDescription, ' ');  	LLStringUtil::replaceChar(mDescription, '|', ' ');  	mPermissions.initMasks(inv_type); @@ -312,9 +327,9 @@ LLInventoryItem::LLInventoryItem() :  	mDescription(),  	mSaleInfo(),  	mInventoryType(LLInventoryType::IT_NONE), -	mFlags(0), -	mCreationDate(0) +	mFlags(0)  { +	mCreationDate = 0;  }  LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) : @@ -379,11 +394,6 @@ const std::string& LLInventoryItem::getDescription() const  	return mDescription;  } -time_t LLInventoryItem::getCreationDate() const -{ -	return mCreationDate; -} -  U32 LLInventoryItem::getCRC32() const  {  	// *FIX: Not a real crc - more of a checksum. @@ -440,11 +450,6 @@ void LLInventoryItem::setFlags(U32 flags)  	mFlags = flags;  } -void LLInventoryItem::setCreationDate(time_t creation_date_utc) -{ -	mCreationDate = creation_date_utc; -} -  // Currently only used in the Viewer to handle calling cards  // where the creator is actually used to store the target.  void LLInventoryItem::setCreator(const LLUUID& creator) @@ -506,6 +511,12 @@ U32 LLInventoryItem::getFlags() const  	return mFlags;  } +time_t LLInventoryItem::getCreationDate() const +{ +	return mCreationDate; +} + +  // virtual  void LLInventoryItem::packMessage(LLMessageSystem* msg) const  { diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index a5cfe59bda..dc9a09e9d6 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -75,6 +75,7 @@ public:  	virtual LLAssetType::EType getType() const;  	LLAssetType::EType getActualType() const; // bypasses indirection for linked items  	BOOL getIsLinkType() const; +	virtual time_t getCreationDate() const;  	//--------------------------------------------------------------------  	// Mutators @@ -85,6 +86,7 @@ public:  	virtual void rename(const std::string& new_name);  	void setParent(const LLUUID& new_parent);  	void setType(LLAssetType::EType type); +	virtual void setCreationDate(time_t creation_date_utc); // only stored for items  private:  	// in place correction for inventory name string @@ -113,6 +115,7 @@ protected:  	LLUUID mParentUUID; // Parent category.  Root categories have LLUUID::NULL.  	LLAssetType::EType mType;  	std::string mName; +	time_t mCreationDate; // seconds from 1/1/1970, UTC  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -178,7 +181,6 @@ public:  	void setPermissions(const LLPermissions& perm);  	void setInventoryType(LLInventoryType::EType inv_type);  	void setFlags(U32 flags); -	void setCreationDate(time_t creation_date_utc);  	void setCreator(const LLUUID& creator); // only used for calling cards  	// Check for changes in permissions masks and sale info @@ -224,7 +226,6 @@ protected:  	LLSaleInfo mSaleInfo;  	LLInventoryType::EType mInventoryType;  	U32 mFlags; -	time_t mCreationDate; // seconds from 1/1/1970, UTC  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 8282d79b67..8807b36117 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -85,6 +85,7 @@ LLInventoryDictionary::LLInventoryDictionary()  	addEntry(LLInventoryType::IT_GESTURE,             new InventoryEntry("gesture",   "gesture",       1, LLAssetType::AT_GESTURE));   	addEntry(LLInventoryType::IT_MESH,                new InventoryEntry("mesh",      "mesh",          1, LLAssetType::AT_MESH));  	addEntry(LLInventoryType::IT_WIDGET,              new InventoryEntry("widget",    "widget",        1, LLAssetType::AT_WIDGET)); +	addEntry(LLInventoryType::IT_PERSON,              new InventoryEntry("person",    "person",        1, LLAssetType::AT_PERSON));  } @@ -140,7 +141,7 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =  	LLInventoryType::IT_NONE,			// 42	AT_NONE  	LLInventoryType::IT_NONE,			// 43	AT_NONE  	LLInventoryType::IT_NONE,			// 44	AT_NONE -	LLInventoryType::IT_NONE,			// 45	AT_NONE +	LLInventoryType::IT_PERSON,			// 45	AT_PERSON  	LLInventoryType::IT_NONE,			// 46	AT_NONE  	LLInventoryType::IT_NONE,			// 47	AT_NONE  	LLInventoryType::IT_NONE,			// 48	AT_NONE diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index 4d1e0db040..645ebab234 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -63,7 +63,8 @@ public:  		IT_GESTURE = 20,  		IT_MESH = 22,  		IT_WIDGET = 23, -		IT_COUNT = 24, +		IT_PERSON = 24, +		IT_COUNT = 25,  		IT_NONE = -1  	}; diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index e26aead676..0e2c3bcb44 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -59,7 +59,6 @@ protected:  	LLGLEnable mColorMaterial;  	LLGLDisable mAlphaTest, mBlend, mCullFace, mDither, mFog,   		mLineSmooth, mLineStipple, mNormalize, mPolygonSmooth, -		mTextureGenQ, mTextureGenR, mTextureGenS, mTextureGenT,  		mGLMultisample;  public:  	LLGLSDefault() @@ -76,10 +75,6 @@ public:  		mLineStipple(GL_LINE_STIPPLE),  		mNormalize(GL_NORMALIZE),  		mPolygonSmooth(GL_POLYGON_SMOOTH), -		mTextureGenQ(GL_TEXTURE_GEN_Q),  -		mTextureGenR(GL_TEXTURE_GEN_R), -		mTextureGenS(GL_TEXTURE_GEN_S),  -		mTextureGenT(GL_TEXTURE_GEN_T),  		mGLMultisample(GL_MULTISAMPLE_ARB)  	{ }  }; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 348c1eb1b7..4597d06260 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -648,7 +648,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT  		gGL.flush();  		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);  	} - +	  	// We want an early out, because this function does a LOT of stuff.  	if ( ( (isAlpha && (mCurrAlphaOp == op) && (mCurrAlphaSrc1 == src1) && (mCurrAlphaSrc2 == src2))  			|| (!isAlpha && (mCurrColorOp == op) && (mCurrColorSrc1 == src1) && (mCurrColorSrc2 == src2)) ) && !gGL.mDirty) @@ -1437,6 +1437,17 @@ void LLRender::matrixMode(U32 mode)  	mMatrixMode = mode;  } +U32 LLRender::getMatrixMode() +{ +	if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3) +	{ //always return MM_TEXTURE if current matrix mode points at any texture matrix +		return MM_TEXTURE; +	} + +	return mMatrixMode; +} + +  void LLRender::loadIdentity()  {  	flush(); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index fa5f7f311d..78a310e525 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -346,6 +346,7 @@ public:  	void loadIdentity();  	void multMatrix(const GLfloat* m);  	void matrixMode(U32 mode);	 +	U32 getMatrixMode();  	const glh::matrix4f& getModelviewMatrix();  	const glh::matrix4f& getProjectionMatrix(); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index a9248d4d73..b6a9a6b653 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -643,7 +643,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  		text[count++] = strdup("#define textureCube texture\n");  		text[count++] = strdup("#define texture2DLod textureLod\n");  		text[count++] = strdup("#define	shadow2D(a,b) vec2(texture(a,b))\n"); - +		  		if (major_version > 1 || minor_version >= 40)  		{ //GLSL 1.40 replaces texture2DRect et al with texture  			text[count++] = strdup("#define texture2DRect texture\n"); diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index eadef93c89..28a14b23b9 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -291,6 +291,7 @@ void LLVBOPool::seedPool() +  void LLVBOPool::cleanup()  {  	U32 size = LL_VBO_BLOCK_SIZE; diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index cca4ca3981..bc225593d8 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -33,6 +33,7 @@ set(llui_SOURCE_FILES      llbadgeholder.cpp      llbadgeowner.cpp      llbutton.cpp +    llchatentry.cpp      llcheckboxctrl.cpp      llclipboard.cpp      llcombobox.cpp @@ -52,6 +53,9 @@ set(llui_SOURCE_FILES      llfloaterreglistener.cpp      llflyoutbutton.cpp       llfocusmgr.cpp +    llfolderview.cpp +    llfolderviewitem.cpp +    llfolderviewmodel.cpp      llfunctorregistry.cpp      lliconctrl.cpp      llkeywords.cpp @@ -135,6 +139,7 @@ set(llui_HEADER_FILES      llbadgeowner.h      llbutton.h      llcallbackmap.h +    llchatentry.h      llcheckboxctrl.h      llclipboard.h      llcombobox.h @@ -154,6 +159,9 @@ set(llui_HEADER_FILES      llfloaterreglistener.h      llflyoutbutton.h       llfocusmgr.h +    llfolderview.h +    llfolderviewitem.h +    llfolderviewmodel.h      llfunctorregistry.h      llhandle.h      llhelp.h diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index c025cd7939..43462bd244 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -184,7 +184,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleFontStyle(std::string  	if (mHeaderTextbox)  	{  		std::string text = mHeaderTextbox->getText(); -		mStyleParams.font(mHeaderTextbox->getDefaultFont()); +		mStyleParams.font(mHeaderTextbox->getFont());  		mStyleParams.font.style(style);  		mHeaderTextbox->setText(text, mStyleParams);  	} diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp new file mode 100644 index 0000000000..2a6ccc3dc9 --- /dev/null +++ b/indra/llui/llchatentry.cpp @@ -0,0 +1,199 @@ +/** + * @file llchatentry.cpp + * @brief LLChatEntry implementation + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llchatentry.h" + +static LLDefaultChildRegistry::Register<LLChatEntry> r("chat_editor"); + +LLChatEntry::Params::Params() +:	has_history("has_history", true), + 	is_expandable("is_expandable", false), + 	expand_lines_count("expand_lines_count", 1) +{} + +LLChatEntry::LLChatEntry(const Params& p) +:	LLTextEditor(p), + 	mTextExpandedSignal(NULL), + 	mHasHistory(p.has_history), + 	mIsExpandable(p.is_expandable), + 	mExpandLinesCount(p.expand_lines_count), + 	mPrevLinesCount(0) +{ +	// Initialize current history line iterator +	mCurrentHistoryLine = mLineHistory.begin(); + +	mAutoIndent = false; +} + +LLChatEntry::~LLChatEntry() +{ +	delete mTextExpandedSignal; +} + +void LLChatEntry::draw() +{ +	if(mIsExpandable) +	{ +		expandText(); +	} + +	LLTextEditor::draw(); +} + +void LLChatEntry::onCommit() +{ +	updateHistory(); +	LLTextEditor::onCommit(); +} + +boost::signals2::connection LLChatEntry::setTextExpandedCallback(const commit_signal_t::slot_type& cb) +{ +	if (!mTextExpandedSignal) +	{ +		mTextExpandedSignal = new commit_signal_t(); +	} +	return mTextExpandedSignal->connect(cb); +} + +void LLChatEntry::expandText() +{ +	int visible_lines_count = llabs(getVisibleLines(true).first - getVisibleLines(true).second); +	bool can_expand = getLineCount() <= mExpandLinesCount; + +	// true if pasted text has more lines than expand height limit and expand limit is not reached yet +	bool text_pasted = (getLineCount() > mExpandLinesCount) && (visible_lines_count < mExpandLinesCount); + +	if (mIsExpandable && (can_expand || text_pasted) && getLineCount() != mPrevLinesCount) +	{ +		int lines_height = 0; +		if (text_pasted) +		{ +			// text is pasted and now mLineInfoList.size() > mExpandLineCounts and mLineInfoList is not empty, +			// so lines_height is the sum of the last 'mExpandLinesCount' lines height +			lines_height = (mLineInfoList.end() - mExpandLinesCount)->mRect.mTop - mLineInfoList.back().mRect.mBottom; +		} +		else +		{ +			lines_height = mLineInfoList.begin()->mRect.mTop - mLineInfoList.back().mRect.mBottom; +		} + +		int height = mVPad * 2 +  lines_height; + +		LLRect doc_rect = getRect(); +		doc_rect.setOriginAndSize(doc_rect.mLeft, doc_rect.mBottom, doc_rect.getWidth(), height); +		setShape(doc_rect); + +		mPrevLinesCount = getLineCount(); + +		if (mTextExpandedSignal) +		{ +			(*mTextExpandedSignal)(this, LLSD() ); +		} +	} +} + +// line history support +void LLChatEntry::updateHistory() +{ +	// On history enabled, remember committed line and +	// reset current history line number. +	// Be sure only to remember lines that are not empty and that are +	// different from the last on the list. +	if (mHasHistory && getLength()) +	{ +		// Add text to history, ignoring duplicates +		if (mLineHistory.empty() || getText() != mLineHistory.back()) +		{ +			mLineHistory.push_back(getText()); +		} + +		mCurrentHistoryLine = mLineHistory.end(); +	} +} + +BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) +{ +	BOOL handled = FALSE; + +	LLTextEditor::handleSpecialKey(key, mask); + +	switch(key) +	{ +	case KEY_RETURN: +		if (MASK_NONE == mask) +		{ +			needsReflow(); +		} +		break; + +	case KEY_UP: +		if (mHasHistory && MASK_CONTROL == mask) +		{ +			if (!mLineHistory.empty() && mCurrentHistoryLine > mLineHistory.begin()) +			{ +				setText(*(--mCurrentHistoryLine)); +				endOfDoc(); +			} +			else +			{ +				LLUI::reportBadKeystroke(); +			} +			handled = TRUE; +		} +		break; + +	case KEY_DOWN: +		if (mHasHistory && MASK_CONTROL == mask) +		{ +			if (!mLineHistory.empty() && mCurrentHistoryLine < (mLineHistory.end() - 1) ) +			{ +				setText(*(++mCurrentHistoryLine)); +				endOfDoc(); +			} +			else if (!mLineHistory.empty() && mCurrentHistoryLine == (mLineHistory.end() - 1) ) +			{ +				mCurrentHistoryLine++; +				std::string empty(""); +				setText(empty); +				needsReflow(); +				endOfDoc(); +			} +			else +			{ +				LLUI::reportBadKeystroke(); +			} +			handled = TRUE; +		} +		break; + +	default: +		break; +	} + +	return handled; +} diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h new file mode 100644 index 0000000000..10a4594e83 --- /dev/null +++ b/indra/llui/llchatentry.h @@ -0,0 +1,98 @@ +/** + * @file llchatentry.h + * @author Paul Guslisty + * @brief Text editor widget which is used for user input + * + * Features: + *			Optional line history so previous entries can be recalled by CTRL UP/DOWN + *			Optional auto-resize behavior on input chat field + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLCHATENTRY_H_ +#define LLCHATENTRY_H_ + +#include "lltexteditor.h" + +class LLChatEntry : public LLTextEditor +{ +public: + +	struct Params : public LLInitParam::Block<Params, LLTextEditor::Params> +	{ +		Optional<bool>		has_history, +							is_expandable; + +		Optional<int>		expand_lines_count; + +		Params(); +	}; + +	virtual ~LLChatEntry(); + +protected: + +	friend class LLUICtrlFactory; +	LLChatEntry(const Params& p); + +public: + +	virtual void	draw(); +	virtual	void	onCommit(); + +	boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); + +private: + +	/** +	 * Implements auto-resize behavior. +	 * When user's typing reaches the right edge of the chat field +	 * the chat field expands vertically by one line. The bottom of +	 * the chat field remains bottom-justified. The chat field does +	 * not expand beyond mExpandLinesCount. +	 */ +	void	expandText(); + +	/** +	 * Implements line history so previous entries can be recalled by CTRL UP/DOWN +	 */ +	void	updateHistory(); + +	BOOL	handleSpecialKey(const KEY key, const MASK mask); + + +	// Fired when text height expanded to mExpandLinesCount +	commit_signal_t*			mTextExpandedSignal; + +	// line history support: +	typedef std::vector<std::string>	line_history_t; +	line_history_t::iterator			mCurrentHistoryLine;	// currently browsed history line +	line_history_t						mLineHistory;			// line history storage +	bool								mHasHistory;			// flag for enabled/disabled line history +	bool								mIsExpandable; + +	int									mExpandLinesCount; +	int									mPrevLinesCount; +}; + +#endif /* LLCHATENTRY_H_ */ diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8ca1e685a9..8145d6d347 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1175,7 +1175,6 @@ void LLFloater::setMinimized(BOOL minimize)  	{  		// minimized flag should be turned on before release focus  		mMinimized = TRUE; -  		mExpandedRect = getRect();  		// If the floater has been dragged while minimized in the @@ -1248,7 +1247,6 @@ void LLFloater::setMinimized(BOOL minimize)  		}  		setOrigin( mExpandedRect.mLeft, mExpandedRect.mBottom ); -  		if (mButtonsEnabled[BUTTON_RESTORE])  		{  			mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; @@ -1284,7 +1282,6 @@ void LLFloater::setMinimized(BOOL minimize)  		// Reshape *after* setting mMinimized  		reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); -		applyPositioning(NULL, false);  	}  	make_ui_sound("UISndWindowClose"); @@ -1406,7 +1403,6 @@ void LLFloater::setHost(LLMultiFloater* host)  		mButtonScale = 1.f;  		//mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE;  	} -	updateTitleButtons();  	if (host)  	{  		mHostHandle = host->getHandle(); @@ -1416,6 +1412,8 @@ void LLFloater::setHost(LLMultiFloater* host)  	{  		mHostHandle.markDead();  	} +     +	updateTitleButtons();  }  void LLFloater::moveResizeHandlesToFront() @@ -1657,10 +1655,12 @@ void LLFloater::onClickTearOff(LLFloater* self)  		gFloaterView->addChild(self);  		self->openFloater(self->getKey()); -		 -		// only force position for floaters that don't have that data saved -		if (self->mRectControl.empty()) +		if (self->mSaveRect && !self->mRectControl.empty())  		{ +			self->applyRectControl(); +		} +		else +		{   // only force position for floaters that don't have that data saved  			new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight());  			self->setRect(new_rect);  		} @@ -1674,6 +1674,10 @@ void LLFloater::onClickTearOff(LLFloater* self)  		LLMultiFloater* new_host = (LLMultiFloater*)self->mLastHostHandle.get();  		if (new_host)  		{ +			if (self->mSaveRect) +			{ +				self->storeRectControl(); +			}  			self->setMinimized(FALSE); // to reenable minimize button if it was minimized  			new_host->showFloater(self);  			// make sure host is visible @@ -1682,6 +1686,7 @@ void LLFloater::onClickTearOff(LLFloater* self)  		self->setTornOff(false);  	}  	self->updateTitleButtons(); +    self->setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE);  }  // static @@ -1707,6 +1712,18 @@ void LLFloater::onClickHelp( LLFloater* self )  	}  } +void LLFloater::initRectControl() +{ +	// save_rect and save_visibility only apply to registered floaters +	if (mSaveRect) +	{ +		std::string ctrl_name = getControlName(mInstanceName, mKey); +		mRectControl = LLFloaterReg::declareRectControl(ctrl_name); +		mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name); +		mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name); +	} +} +  // static   LLFloater* LLFloater::getClosableFloaterFromFocus()  { @@ -2938,28 +2955,22 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)  void LLFloater::setInstanceName(const std::string& name)  { -	if (name == mInstanceName) -		return; -	llassert_always(mInstanceName.empty()); -	mInstanceName = name; -	if (!mInstanceName.empty()) +	if (name != mInstanceName)  	{ -		std::string ctrl_name = getControlName(mInstanceName, mKey); - -		// save_rect and save_visibility only apply to registered floaters -		if (mSaveRect) -		{ -			mRectControl = LLFloaterReg::declareRectControl(ctrl_name); -			mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name); -			mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name); -		} -		if (!mVisibilityControl.empty()) +		llassert_always(mInstanceName.empty()); +		mInstanceName = name; +		if (!mInstanceName.empty())  		{ -			mVisibilityControl = LLFloaterReg::declareVisibilityControl(ctrl_name); -		} -		if(!mDocStateControl.empty()) -		{ -			mDocStateControl = LLFloaterReg::declareDockStateControl(ctrl_name); +			std::string ctrl_name = getControlName(mInstanceName, mKey); +			initRectControl(); +			if (!mVisibilityControl.empty()) +			{ +				mVisibilityControl = LLFloaterReg::declareVisibilityControl(ctrl_name); +			} +			if(!mDocStateControl.empty()) +			{ +				mDocStateControl = LLFloaterReg::declareDockStateControl(ctrl_name); +			}  		}  	}  } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 64d6dcea04..a1cac64a4a 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -324,6 +324,8 @@ public:  	virtual void    setDocked(bool docked, bool pop_on_undock = true);  	virtual void    setTornOff(bool torn_off) { mTornOff = torn_off; } +	bool isTornOff() {return mTornOff;} +	void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mPositioning = pos;}  	// Return a closeable floater, if any, given the current focus.  	static LLFloater* getClosableFloaterFromFocus();  @@ -356,6 +358,7 @@ protected:  	void			stackWith(LLFloater& other); +	virtual void    initRectControl();  	virtual bool	applyRectControl();  	bool			applyDockState();  	void			applyPositioning(LLFloater* other, bool on_open); diff --git a/indra/newview/llfolderview.cpp b/indra/llui/llfolderview.cpp index d4080ab3f7..11004fe390 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -24,39 +24,20 @@   * $/LicenseInfo$   */ -#include "llviewerprecompiledheaders.h" +#include "linden_common.h"  #include "llfolderview.h" - -#include "llcallbacklist.h" -#include "llinventorybridge.h" +#include "llfolderviewmodel.h"  #include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llinventoryfilter.h" -#include "llinventoryfunctions.h" -#include "llinventorymodelbackgroundfetch.h" -#include "llinventorypanel.h" -#include "llfoldertype.h" -#include "llfloaterinventory.h"// hacked in for the bonus context menu items.  #include "llkeyboard.h"  #include "lllineeditor.h"  #include "llmenugl.h"  #include "llpanel.h" -#include "llpreview.h"  #include "llscrollcontainer.h" // hack to allow scrolling -#include "lltooldraganddrop.h" +#include "lltextbox.h"  #include "lltrans.h"  #include "llui.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llviewerjointattachment.h" -#include "llviewermenu.h"  #include "lluictrlfactory.h" -#include "llviewercontrol.h" -#include "llviewerfoldertype.h" -#include "llviewerwindow.h" -#include "llvoavatar.h" -#include "llfloaterproperties.h" -#include "llnotificationsutil.h"  // Linden library includes  #include "lldbstrings.h" @@ -64,7 +45,6 @@  #include "llfontgl.h"  #include "llgl.h"   #include "llrender.h" -#include "llinventory.h"  // Third-party library includes  #include <algorithm> @@ -94,42 +74,6 @@ enum {  F32 LLFolderView::sAutoOpenTime = 1.f; -void delete_selected_item(void* user_data); -void copy_selected_item(void* user_data); -void open_selected_items(void* user_data); -void properties_selected_items(void* user_data); -void paste_items(void* user_data); - - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to sort their items -// (and only their items, not folders) by a certain function. -class LLSetItemSortFunction : public LLFolderViewFunctor -{ -public: -	LLSetItemSortFunction(U32 ordering) -		: mSortOrder(ordering) {} -	virtual ~LLSetItemSortFunction() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); - -	U32 mSortOrder; -}; - - -// Set the sort order. -void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder) -{ -	folder->setItemSortOrder(mSortOrder); -} - -// Do nothing. -void LLSetItemSortFunction::doItem(LLFolderViewItem* item) -{ -	return; -} -  //---------------------------------------------------------------------------  // Tells all folders in a folderview to close themselves @@ -154,7 +98,6 @@ public:  }; -// Set the sort order.  void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder)  {  	folder->setOpenArrangeRecursively(mOpen); @@ -177,7 +120,7 @@ const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const  		LLFolderView* folder_view = dynamic_cast<LLFolderView*>(mScrolledView);  		if (folder_view)  		{ -			S32 height = folder_view->mRunningHeight; +			S32 height = folder_view->getRect().getHeight();  			rect = mScrolledView->getRect();  			rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); @@ -195,27 +138,24 @@ LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer  /// Class LLFolderView  ///----------------------------------------------------------------------------  LLFolderView::Params::Params() -:	task_id("task_id"), -	title("title"), +:	title("title"),  	use_label_suffix("use_label_suffix"),  	allow_multiselect("allow_multiselect", true),  	show_empty_message("show_empty_message", true), -	show_load_status("show_load_status", true),  	use_ellipses("use_ellipses", false)  { +	folder_indentation = -4;  }  // Default constructor  LLFolderView::LLFolderView(const Params& p)  :	LLFolderViewFolder(p), -	mRunningHeight(0),  	mScrollContainer( NULL ),  	mPopupMenuHandle(),  	mAllowMultiSelect(p.allow_multiselect),  	mShowEmptyMessage(p.show_empty_message),  	mShowFolderHierarchy(FALSE), -	mSourceID(p.task_id),  	mRenameItem( NULL ),  	mNeedsScroll( FALSE ),  	mUseLabelSuffix(p.use_label_suffix), @@ -223,9 +163,6 @@ LLFolderView::LLFolderView(const Params& p)  	mNeedsAutoSelect( FALSE ),  	mAutoSelectOverride(FALSE),  	mNeedsAutoRename(FALSE), -	mDebugFilters(FALSE), -	mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME),	// This gets overridden by a pref immediately -	mFilter( new LLInventoryFilter(p.title) ),  	mShowSelectionContext(FALSE),  	mShowSingleSelection(FALSE),  	mArrangeGeneration(0), @@ -236,33 +173,28 @@ LLFolderView::LLFolderView(const Params& p)  	mParentPanel(p.parent_panel),  	mUseEllipses(p.use_ellipses),  	mDraggingOverItem(NULL), -	mStatusTextBox(NULL) +	mStatusTextBox(NULL), +	mShowItemLinkOverlays(p.show_item_link_overlays), +	mViewModel(p.view_model)  { +	mViewModel->setFolderView(this);  	mRoot = this; -	mShowLoadStatus = p.show_load_status(); -  	LLRect rect = p.rect;  	LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom);  	setRect( rect );  	reshape(rect.getWidth(), rect.getHeight()); -	mIsOpen = TRUE; // this view is always open.  	mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH);  	mAutoOpenCandidate = NULL;  	mAutoOpenTimer.stop();  	mKeyboardSelection = FALSE; -	const LLFolderViewItem::Params& item_params = -		LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); -	S32 indentation = item_params.folder_indentation(); -	mIndentation = -indentation; // children start at indentation 0 -	gIdleCallbacks.addFunction(idle, this); +	mIndentation = p.folder_indentation;  	//clear label  	// go ahead and render root folder as usual  	// just make sure the label ("Inventory Folder") never shows up  	mLabel = LLStringUtil::null; -	//mRenamer->setWriteableBgColor(LLColor4::white);  	// Escape is handled by reverting the rename, not commiting it (default behavior)  	LLLineEditor::Params params;  	params.name("ren"); @@ -299,7 +231,7 @@ LLFolderView::LLFolderView(const Params& p)  	// make the popup menu available -	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());  	if (!menu)  	{  		menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); @@ -307,7 +239,7 @@ LLFolderView::LLFolderView(const Params& p)  	menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));  	mPopupMenuHandle = menu->getHandle(); -	mListener->openItem(); +	mViewModelItem->openItem();  }  // Destroys the object @@ -326,7 +258,6 @@ LLFolderView::~LLFolderView( void )  	mStatusTextBox = NULL;  	mAutoOpenItems.removeAllNodes(); -	gIdleCallbacks.deleteFunction(idle, this);  	if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); @@ -335,10 +266,7 @@ LLFolderView::~LLFolderView( void )  	mItems.clear();  	mFolders.clear(); -	mItemMap.clear(); - -	delete mFilter; -	mFilter = NULL; +	mViewModel = NULL;  }  BOOL LLFolderView::canFocusChildren() const @@ -346,47 +274,21 @@ BOOL LLFolderView::canFocusChildren() const  	return FALSE;  } -static LLFastTimer::DeclareTimer FTM_SORT("Sort Inventory"); - -void LLFolderView::setSortOrder(U32 order) +void LLFolderView::addFolder( LLFolderViewFolder* folder)  { -	if (order != mSortOrder) -	{ -		LLFastTimer t(FTM_SORT); +	LLFolderViewFolder::addFolder(folder); -		mSortOrder = order; - -		sortBy(order); -		arrangeAll(); +	// TODO RN: enforce sort order of My Inventory followed by Library +	//mFolders.remove(folder); +	//if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) +	//{ +	//	mFolders.push_back(folder); +	//} +	//else +	//{ +	//	mFolders.insert(mFolders.begin(), folder); +	//}  	} -} - - -U32 LLFolderView::getSortOrder() const -{ -	return mSortOrder; -} - -BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) -{ -	// enforce sort order of My Inventory followed by Library -	if (folder->getListener()->getUUID() == gInventory.getLibraryRootFolderID()) -	{ -		mFolders.push_back(folder); -	} -	else -	{ -		mFolders.insert(mFolders.begin(), folder); -	} -	folder->setShowLoadStatus(mShowLoadStatus); -	folder->setOrigin(0, 0); -	folder->reshape(getRect().getWidth(), 0); -	folder->setVisible(FALSE); -	addChild( folder ); -	folder->dirtyFilter(); -	folder->requestArrange(); -	return TRUE; -}  void LLFolderView::closeAllFolders()  { @@ -405,145 +307,39 @@ void LLFolderView::openTopLevelFolders()  	}  } -void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ -	// call base class to do proper recursion -	LLFolderViewFolder::setOpenArrangeRecursively(openitem, recurse); -	// make sure root folder is always open -	mIsOpen = TRUE; -} - -static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); -  // This view grows and shrinks to enclose all of its children items and folders. -S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) -{ -	if (getListener()->getUUID().notNull()) -	{ -		if (mNeedsSort) +// *width should be 0 +// conform show folder state works +S32 LLFolderView::arrange( S32* unused_width, S32* unused_height )  		{ -			mFolders.sort(mSortFunction); -			mItems.sort(mSortFunction); -			mNeedsSort = false; -		} -	} - -	LLFastTimer t2(FTM_ARRANGE); - -	filter_generation = mFilter->getMinRequiredGeneration();  	mMinWidth = 0; +	S32 target_height; -	mHasVisibleChildren = hasFilteredDescendants(filter_generation); -	// arrange always finishes, so optimistically set the arrange generation to the most current -	mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - -	LLInventoryFilter::EFolderShow show_folder_state = -		getRoot()->getFilter()->getShowFolderState(); +	LLFolderViewFolder::arrange(&mMinWidth, &target_height); -	S32 total_width = LEFT_PAD; -	S32 running_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; -	S32 target_height = running_height; -	S32 parent_item_height = getRect().getHeight(); +	LLRect scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); +	reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		LLFolderViewFolder* folderp = (*fit); -		if (getDebugFilters()) -		{ -			folderp->setVisible(TRUE); -		} -		else -		{ -			folderp->setVisible((show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? -								 (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation)))); -		} - -		if (folderp->getVisible()) -		{ -			S32 child_height = 0; -			S32 child_width = 0; -			S32 child_top = parent_item_height - running_height; -			 -			target_height += folderp->arrange( &child_width, &child_height, filter_generation ); - -			mMinWidth = llmax(mMinWidth, child_width); -			total_width = llmax( total_width, child_width ); -			running_height += child_height; -			folderp->setOrigin( ICON_PAD, child_top - (*fit)->getRect().getHeight() ); -		} -	} - -	for (items_t::iterator iter = mItems.begin(); -		 iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		LLFolderViewItem* itemp = (*iit); -		itemp->setVisible(itemp->getFiltered(filter_generation)); - -		if (itemp->getVisible()) -		{ -			S32 child_width = 0; -			S32 child_height = 0; -			S32 child_top = parent_item_height - running_height; -			 -			target_height += itemp->arrange( &child_width, &child_height, filter_generation ); -			itemp->reshape(itemp->getRect().getWidth(), child_height); - -			mMinWidth = llmax(mMinWidth, child_width); -			total_width = llmax( total_width, child_width ); -			running_height += child_height; -			itemp->setOrigin( ICON_PAD, child_top - itemp->getRect().getHeight() ); -		} -	} - -	if(!mHasVisibleChildren)// is there any filtered items ? -	{ -		//Nope. We need to display status textbox, let's reserve some place for it -		running_height = mStatusTextBox->getTextPixelHeight(); -		target_height = running_height; -	} - -	mRunningHeight = running_height; -	LLRect scroll_rect = mScrollContainer->getContentWindowRect(); -	reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); - -	LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); +	LLRect new_scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect());  	if (new_scroll_rect.getWidth() != scroll_rect.getWidth())  	{ -		reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); +		reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) );  	}  	// move item renamer text field to item's new position  	updateRenamerPosition(); -	mTargetHeight = (F32)target_height;  	return llround(mTargetHeight);  } -const std::string LLFolderView::getFilterSubString(BOOL trim) -{ -	return mFilter->getFilterSubString(trim); -} - -static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory"); +static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); -void LLFolderView::filter( LLInventoryFilter& filter ) +void LLFolderView::filter( LLFolderViewFilter& filter )  {  	LLFastTimer t2(FTM_FILTER); -	filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); +	filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); -	if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) -	{ -		mPassedFilter = FALSE; -		mMinWidth = 0; -		LLFolderViewFolder::filter(filter); -	} -	else -	{ -		mPassedFilter = TRUE; -	} +	getViewModelItem()->filter(filter);  }  void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -555,7 +351,7 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)  		scroll_rect = mScrollContainer->getContentWindowRect();  	}  	width  = llmax(mMinWidth, scroll_rect.getWidth()); -	height = llmax(mRunningHeight, scroll_rect.getHeight()); +	height = llmax(llround(mCurHeight), scroll_rect.getHeight());  	// Restrict width within scroll container's width  	if (mUseEllipses && mScrollContainer) @@ -653,30 +449,6 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem,  	return rv;  } -void LLFolderView::setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus) -{ -	LLFolderViewItem* itemp = getItemByID(obj_id); -	if(itemp && itemp->getListener()) -	{ -		itemp->arrangeAndSet(TRUE, take_keyboard_focus); -		mSelectThisID.setNull(); -		return; -	} -	else -	{ -		// save the desired item to be selected later (if/when ready) -		mSelectThisID = obj_id; -	} -} - -void LLFolderView::updateSelection() -{ -	if (mSelectThisID.notNull()) -	{ -		setSelectionByID(mSelectThisID, false); -	} -} -  BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected)  {  	BOOL rv = FALSE; @@ -727,9 +499,6 @@ void LLFolderView::sanitizeSelection()  	// and we want to preserve context  	LLFolderViewItem* original_selected_item = getCurSelectedItem(); -	// Cache "Show all folders" filter setting -	BOOL show_all_folders = (getRoot()->getFilter()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); -  	std::vector<LLFolderViewItem*> items_to_remove;  	selected_items_t::iterator item_iter;  	for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) @@ -737,24 +506,15 @@ void LLFolderView::sanitizeSelection()  		LLFolderViewItem* item = *item_iter;  		// ensure that each ancestor is open and potentially passes filtering -		BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item +		BOOL visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item  		// modify with parent open and filters states  		LLFolderViewFolder* parent_folder = item->getParentFolder(); -		if ( parent_folder ) -		{ -			if ( show_all_folders ) -			{	// "Show all folders" is on, so this folder is visible -				visible = TRUE; -			} -			else -			{	// Move up through parent folders and see what's visible +		// Move up through parent folders and see what's visible  				while(parent_folder)  				{ -					visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); +			visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible();  					parent_folder = parent_folder->getParentFolder();  				} -			} -		}  		//  deselect item if any ancestor is closed or didn't pass filter requirements.  		if (!visible) @@ -804,7 +564,7 @@ void LLFolderView::sanitizeSelection()  				parent_folder;  				parent_folder = parent_folder->getParentFolder())  			{ -				if (parent_folder->potentiallyVisible()) +				if (parent_folder->getViewModelItem()->potentiallyVisible())  				{  					// give initial selection to first ancestor folder that potentially passes the filter  					if (!new_selection) @@ -843,42 +603,30 @@ void LLFolderView::clearSelection()  	}  	mSelectedItems.clear(); -	mSelectThisID.setNull();  } -std::set<LLUUID> LLFolderView::getSelectionList() const +std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const  { -	std::set<LLUUID> selection; -	for (selected_items_t::const_iterator item_it = mSelectedItems.begin();  -		 item_it != mSelectedItems.end();  -		 ++item_it) -	{ -		selection.insert((*item_it)->getListener()->getUUID()); -	} +	std::set<LLFolderViewItem*> selection; +	std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin()));  	return selection;  } -BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source) +bool LLFolderView::startDrag()  { -	std::vector<EDragAndDropType> types; -	uuid_vec_t cargo_ids; +	std::vector<LLFolderViewModelItem*> selected_items;  	selected_items_t::iterator item_it; -	BOOL can_drag = TRUE; +  	if (!mSelectedItems.empty())  	{  		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)  		{ -			EDragAndDropType type = DAD_NONE; -			LLUUID id = LLUUID::null; -			can_drag = can_drag && (*item_it)->getListener()->startDrag(&type, &id); - -			types.push_back(type); -			cargo_ids.push_back(id); +			selected_items.push_back((*item_it)->getViewModelItem());  		} -		LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, source, mSourceID);  +		return getFolderViewModel()->startDrag(selected_items);  	} -	return can_drag; +	return false;  }  void LLFolderView::commitRename( const LLSD& data ) @@ -888,16 +636,6 @@ void LLFolderView::commitRename( const LLSD& data )  void LLFolderView::draw()  { -	static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", LLColor4::white); -	if (mDebugFilters) -	{ -		std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", -										mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration()); -		LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2,  -			getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f),  -			LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); -	} -  	//LLFontGL* font = getLabelFontForStyle(mLabelStyle);  	// if cursor has moved off of me during drag and drop @@ -907,52 +645,18 @@ void LLFolderView::draw()  		closeAutoOpenedFolders();  	} -	// while dragging, update selection rendering to reflect single/multi drag status -	if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) -	{ -		EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); -		if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) -		{ -			setShowSingleSelection(TRUE); -		} -		else -		{ -			setShowSingleSelection(FALSE); -		} -	} -	else -	{ -		setShowSingleSelection(FALSE); -	} - - -	if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout") || !mSearchString.size()) +	if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size())  	{  		mSearchString.clear();  	} -	if (hasVisibleChildren() -		|| mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) +	if (hasVisibleChildren())  	{ -		mStatusText.clear();  		mStatusTextBox->setVisible( FALSE );  	}  	else if (mShowEmptyMessage)  	{ -		if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) -		{ -			mStatusText = LLTrans::getString("Searching"); -		} -		else -		{ -			if (getFilter()) -			{ -				LLStringUtil::format_map_t args; -				args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig()); -				mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args); -			} -		} -		mStatusTextBox->setValue(mStatusText); +		mStatusTextBox->setValue(getFolderViewModel()->getStatusText());  		mStatusTextBox->setVisible( TRUE );  		// firstly reshape message textbox with current size. This is necessary to @@ -969,7 +673,11 @@ void LLFolderView::draw()  			// This will indirectly call ::arrange and reshape of the status textbox.  			// We should call this method to also notify parent about required rect.  			// See EXT-7564, EXT-7047. -			arrangeFromRoot(); +			S32 height = 0; +			S32 width = 0; +			S32 total_height = arrange( &width, &height ); +			notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); +  			LLUI::popMatrix();  			LLUI::pushMatrix();  			LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); @@ -996,7 +704,7 @@ void LLFolderView::finishRenamingItem( void )  	closeRenamer(); -	// List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. +	// List is re-sorted alphabetically, so scroll to make sure the selected item is visible.  	scrollToShowSelection();  } @@ -1005,68 +713,12 @@ void LLFolderView::closeRenamer( void )  	if (mRenamer && mRenamer->getVisible())  	{  		// Triggers onRenamerLost() that actually closes the renamer. -		gViewerWindow->removePopup(mRenamer); +		LLUI::removePopup(mRenamer);  	}  } -void LLFolderView::removeSelectedItems( void ) -{ -	if (mSelectedItems.empty()) return; -	LLSD args; -	args["QUESTION"] = LLTrans::getString(mSelectedItems.size() > 1 ? "DeleteItems" :  "DeleteItem"); -	LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLFolderView::onItemsRemovalConfirmation, this, _1, _2)); -} - -bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFolderViewItem*>& selectedItems) -{ -	LLFolderViewItem* item_parent = dynamic_cast<LLFolderViewItem*>(item->getParent()); - -	if (item_parent) -	{ -		for(std::vector<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) -		{ -			const LLFolderViewItem* const selected_item = (*it); - -			LLFolderViewItem* parent = item_parent; - -			while (parent) -			{ -				if (selected_item == parent) -				{ -					return true; -				} - -				parent = dynamic_cast<LLFolderViewItem*>(parent->getParent()); -			} -		} -	} - -	return false; -} - -// static -void LLFolderView::removeCutItems() +void LLFolderView::removeSelectedItems()  { -	// There's no item in "cut" mode on the clipboard -> exit -	if (!LLClipboard::instance().isCutMode()) -		return; - -	// Get the list of clipboard item uuids and iterate through them -	LLDynamicArray<LLUUID> objects; -	LLClipboard::instance().pasteFromClipboard(objects); -	for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); -		 iter != objects.end(); -		 ++iter) -	{ -		gInventory.removeObject(*iter); -	} -} - -void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response) -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); -	if (option != 0) return; // canceled -  	if(getVisible() && getEnabled())  	{  		// just in case we're removing the renaming item. @@ -1097,68 +749,38 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL  		// iterate through the new container.  		count = items.size();  		LLUUID new_selection_id; +		LLFolderViewItem* item_to_select = getNextUnselectedItem(); +  		if(count == 1)  		{  			LLFolderViewItem* item_to_delete = items[0];  			LLFolderViewFolder* parent = item_to_delete->getParentFolder(); -			LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); -			if (!new_selection) -			{ -				new_selection = item_to_delete->getPreviousOpenNode(FALSE); -			}  			if(parent)  			{ -				if (parent->removeItem(item_to_delete)) +				if (item_to_delete->remove())  				{  					// change selection on successful delete -					if (new_selection) -					{ -						setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); -					} -					else -					{ -						setSelectionFromRoot(NULL, mParentPanel->hasFocus()); +					setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus());  					}  				} -			}  			arrangeAll();  		}  		else if (count > 1)  		{ -			LLDynamicArray<LLFolderViewEventListener*> listeners; -			LLFolderViewEventListener* listener; -			LLFolderViewItem* last_item = items[count - 1]; -			LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); -			while(new_selection && new_selection->isSelected()) -			{ -				new_selection = new_selection->getNextOpenNode(FALSE); -			} -			if (!new_selection) -			{ -				new_selection = last_item->getPreviousOpenNode(FALSE); -				while (new_selection && (new_selection->isSelected() || isDescendantOfASelectedItem(new_selection, items))) -				{ -					new_selection = new_selection->getPreviousOpenNode(FALSE); -				} -			} -			if (new_selection) -			{ -				setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); -			} -			else -			{ -				setSelectionFromRoot(NULL, mParentPanel->hasFocus()); -			} +			LLDynamicArray<LLFolderViewModelItem*> listeners; +			LLFolderViewModelItem* listener; + +			setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus());  			for(S32 i = 0; i < count; ++i)  			{ -				listener = items[i]->getListener(); -				if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL)) +				listener = items[i]->getViewModelItem(); +				if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewModelItem*>::FAIL))  				{  					listeners.put(listener);  				}  			} -			listener = listeners.get(0); +			listener = static_cast<LLFolderViewModelItem*>(listeners.get(0));  			if(listener)  			{  				listener->removeBatch(listeners); @@ -1169,81 +791,75 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL  	}  } +// TODO RN: abstract   // open the selected item.  void LLFolderView::openSelectedItems( void )  { -	if(getVisible() && getEnabled()) -	{ -		if (mSelectedItems.size() == 1) -		{ -			mSelectedItems.front()->openItem(); -		} -		else -		{ -			LLMultiPreview* multi_previewp = new LLMultiPreview(); -			LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - -			selected_items_t::iterator item_it; -			for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -			{ -				// IT_{OBJECT,ATTACHMENT} creates LLProperties -				// floaters; others create LLPreviews.  Put -				// each one in the right type of container. -				LLFolderViewEventListener* listener = (*item_it)->getListener(); -				bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); -				if (is_prop) -					LLFloater::setFloaterHost(multi_propertiesp); -				else -					LLFloater::setFloaterHost(multi_previewp); -				(*item_it)->openItem(); -			} - -			LLFloater::setFloaterHost(NULL); -			// *NOTE: LLMulti* will safely auto-delete when open'd -			// without any children. -			multi_previewp->openFloater(LLSD()); -			multi_propertiesp->openFloater(LLSD()); -		} +	//TODO RN: get working again +	//if(getVisible() && getEnabled()) +	//{ +	//	if (mSelectedItems.size() == 1) +	//	{ +	//		mSelectedItems.front()->openItem(); +	//	} +	//	else +	//	{ +	//		LLMultiPreview* multi_previewp = new LLMultiPreview(); +	//		LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + +	//		selected_items_t::iterator item_it; +	//		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) +	//		{ +	//			// IT_{OBJECT,ATTACHMENT} creates LLProperties +	//			// floaters; others create LLPreviews.  Put +	//			// each one in the right type of container. +	//			LLFolderViewModelItemInventory* listener = static_cast<LLFolderViewModelItemInventory*>((*item_it)->getViewModelItem()); +	//			bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); +	//			if (is_prop) +	//				LLFloater::setFloaterHost(multi_propertiesp); +	//			else +	//				LLFloater::setFloaterHost(multi_previewp); +	//			listener->openItem(); +	//		} + +	//		LLFloater::setFloaterHost(NULL); +	//		// *NOTE: LLMulti* will safely auto-delete when open'd +	//		// without any children. +	//		multi_previewp->openFloater(LLSD()); +	//		multi_propertiesp->openFloater(LLSD()); +	//	} +	//}  	} -}  void LLFolderView::propertiesSelectedItems( void )  { -	if(getVisible() && getEnabled()) -	{ -		if (mSelectedItems.size() == 1) -		{ -			LLFolderViewItem* folder_item = mSelectedItems.front(); -			if(!folder_item) return; -			folder_item->getListener()->showProperties(); -		} -		else -		{ -			LLMultiProperties* multi_propertiesp = new LLMultiProperties(); +	//TODO RN: get working again +	//if(getVisible() && getEnabled()) +	//{ +	//	if (mSelectedItems.size() == 1) +	//	{ +	//		LLFolderViewItem* folder_item = mSelectedItems.front(); +	//		if(!folder_item) return; +	//		folder_item->getViewModelItem()->showProperties(); +	//	} +	//	else +	//	{ +	//		LLMultiProperties* multi_propertiesp = new LLMultiProperties(); -			LLFloater::setFloaterHost(multi_propertiesp); +	//		LLFloater::setFloaterHost(multi_propertiesp); -			selected_items_t::iterator item_it; -			for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -			{ -				(*item_it)->getListener()->showProperties(); -			} +	//		selected_items_t::iterator item_it; +	//		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) +	//		{ +	//			(*item_it)->getViewModelItem()->showProperties(); +	//		} -			LLFloater::setFloaterHost(NULL); -			multi_propertiesp->openFloater(LLSD()); -		} -	} +	//		LLFloater::setFloaterHost(NULL); +	//		multi_propertiesp->openFloater(LLSD()); +	//	} +	//}  } -void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type) -{ -	LLFolderBridge *folder_bridge = LLFolderBridge::sSelf.get(); - -	if (!folder_bridge) return; -	LLViewerInventoryCategory *cat = folder_bridge->getCategory(); -	if (!cat) return; -	cat->changeType(new_folder_type); -}  void LLFolderView::autoOpenItem( LLFolderViewFolder* item )  { @@ -1268,7 +884,7 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item )  	mAutoOpenItems.push(item);  	item->setOpen(TRUE); -	LLRect content_rect = mScrollContainer->getContentWindowRect(); +	LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect());  	LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0);  	scrollToShowItem(item, constraint_rect);  } @@ -1329,7 +945,7 @@ BOOL LLFolderView::canCopy() const  	for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)  	{  		const LLFolderViewItem* item = *selected_it; -		if (!item->getListener()->isItemCopyable()) +		if (!item->getViewModelItem()->isItemCopyable())  		{  			return FALSE;  		} @@ -1345,11 +961,11 @@ void LLFolderView::copy()  	S32 count = mSelectedItems.size();  	if(getVisible() && getEnabled() && (count > 0))  	{ -		LLFolderViewEventListener* listener = NULL; +		LLFolderViewModelItem* listener = NULL;  		selected_items_t::iterator item_it;  		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)  		{ -			listener = (*item_it)->getListener(); +			listener = (*item_it)->getViewModelItem();  			if(listener)  			{  				listener->copyToClipboard(); @@ -1369,7 +985,7 @@ BOOL LLFolderView::canCut() const  	for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)  	{  		const LLFolderViewItem* item = *selected_it; -		const LLFolderViewEventListener* listener = item->getListener(); +		const LLFolderViewModelItem* listener = item->getViewModelItem();  		if (!listener || !listener->isItemRemovable())  		{ @@ -1386,17 +1002,21 @@ void LLFolderView::cut()  	S32 count = mSelectedItems.size();  	if(getVisible() && getEnabled() && (count > 0))  	{ -		LLFolderViewEventListener* listener = NULL; +		LLFolderViewItem* item_to_select = getNextUnselectedItem(); +  		selected_items_t::iterator item_it;  		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)  		{ -			listener = (*item_it)->getListener(); +			LLFolderViewItem* item_to_cut = *item_it; +			LLFolderViewModelItem* listener = item_to_cut->getViewModelItem();  			if(listener)  			{  				listener->cutToClipboard(); +				listener->removeItem();  			}  		} -		LLFolderView::removeCutItems(); + +		setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus());  	}  	mSearchString.clear();  } @@ -1415,11 +1035,11 @@ BOOL LLFolderView::canPaste() const  		{  			// *TODO: only check folders and parent folders of items  			const LLFolderViewItem* item = (*item_it); -			const LLFolderViewEventListener* listener = item->getListener(); +			const LLFolderViewModelItem* listener = item->getViewModelItem();  			if(!listener || !listener->isClipboardPasteable())  			{  				const LLFolderViewFolder* folderp = item->getParentFolder(); -				listener = folderp->getListener(); +				listener = folderp->getViewModelItem();  				if (!listener || !listener->isClipboardPasteable())  				{  					return FALSE; @@ -1437,24 +1057,24 @@ void LLFolderView::paste()  	if(getVisible() && getEnabled())  	{  		// find set of unique folders to paste into -		std::set<LLFolderViewItem*> folder_set; +		std::set<LLFolderViewFolder*> folder_set;  		selected_items_t::iterator selected_it;  		for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)  		{  			LLFolderViewItem* item = *selected_it; -			LLFolderViewEventListener* listener = item->getListener(); -			if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) +			LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(item); +			if (folder == NULL)  			{ -				item = item->getParentFolder(); +				folder = item->getParentFolder();  			} -			folder_set.insert(item); +			folder_set.insert(folder);  		} -		std::set<LLFolderViewItem*>::iterator set_iter; +		std::set<LLFolderViewFolder*>::iterator set_iter;  		for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter)  		{ -			LLFolderViewEventListener* listener = (*set_iter)->getListener(); +			LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem();  			if(listener && listener->isClipboardPasteable())  			{  				listener->pasteFromClipboard(); @@ -1476,8 +1096,8 @@ void LLFolderView::startRenamingSelectedItem( void )  	{  		item = mSelectedItems.front();  	} -	if(getVisible() && getEnabled() && (count == 1) && item && item->getListener() && -	   item->getListener()->isItemRenameable()) +	if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && +	   item->getViewModelItem()->isItemRenameable())  	{  		mRenameItem = item; @@ -1490,7 +1110,7 @@ void LLFolderView::startRenamingSelectedItem( void )  		// set focus will fail unless item is visible  		mRenamer->setFocus( TRUE );  		mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); -		gViewerWindow->addPopup(mRenamer); +		LLUI::addPopup(mRenamer);  	}  } @@ -1548,25 +1168,37 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )  	case KEY_PAGE_UP:  		mSearchString.clear(); +		if (mScrollContainer) +		{  		mScrollContainer->pageUp(30); +		}  		handled = TRUE;  		break;  	case KEY_PAGE_DOWN:  		mSearchString.clear(); +		if (mScrollContainer) +		{  		mScrollContainer->pageDown(30); +		}  		handled = TRUE;  		break;  	case KEY_HOME:  		mSearchString.clear(); +		if (mScrollContainer) +		{  		mScrollContainer->goToTop(); +		}  		handled = TRUE;  		break;  	case KEY_END:  		mSearchString.clear(); +		if (mScrollContainer) +		{  		mScrollContainer->goToBottom(); +		}  		break;  	case KEY_DOWN: @@ -1590,12 +1222,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )  					if (next->isSelected())  					{  						// shrink selection -						changeSelectionFromRoot(last_selected, FALSE); +						changeSelection(last_selected, FALSE);  					}  					else if (last_selected->getParentFolder() == next->getParentFolder())  					{  						// grow selection -						changeSelectionFromRoot(next, TRUE); +						changeSelection(next, TRUE);  					}  				}  			} @@ -1654,12 +1286,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )  					if (prev->isSelected())  					{  						// shrink selection -						changeSelectionFromRoot(last_selected, FALSE); +						changeSelection(last_selected, FALSE);  					}  					else if (last_selected->getParentFolder() == prev->getParentFolder())  					{  						// grow selection -						changeSelectionFromRoot(prev, TRUE); +						changeSelection(prev, TRUE);  					}  				}  			} @@ -1762,7 +1394,7 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char)  		}  		//do text search -		if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout")) +		if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout"))  		{  			mSearchString.clear();  		} @@ -1786,7 +1418,7 @@ BOOL LLFolderView::canDoDelete() const  	for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)  	{ -		if (!(*item_it)->getListener()->isItemRemovable()) +		if (!(*item_it)->getViewModelItem()->isItemRemovable())  		{  			return FALSE;  		} @@ -1853,7 +1485,7 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &searc  			}  		} -		const std::string current_item_label(search_item->getSearchableLabel()); +		const std::string current_item_label(search_item->getViewModelItem()->getSearchableName());  		S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size());  		if (!current_item_label.compare(0, search_string_length, upper_case_string))  		{ @@ -1897,7 +1529,7 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )  	S32 count = mSelectedItems.size();  	LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();  	if (   handled -		&& ( count > 0 && (hasVisibleChildren() || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) ) // show menu only if selected items are visible +		&& ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible  		&& menu )  	{  		if (mCallbackRegistrar) @@ -1972,24 +1604,8 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	// by the folder which is the hierarchy root.  	if (!handled)  	{ -		if (getListener()->getUUID().notNull()) -		{  			handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);  		} -		else -		{ -			if (!mFolders.empty()) -			{ -				// dispatch to last folder as a hack to support "Contents" folder in object inventory -				handled = mFolders.back()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); -			} -		} -	} - -	if (handled) -	{ -		lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; -	}  	return handled;  } @@ -2033,9 +1649,6 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr  	if(item)  	{  		LLRect local_rect = item->getLocalRect(); -		LLRect item_scrolled_rect; // item position relative to display area of scroller -		LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); -		  		S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight();   		S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight();   		// when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder @@ -2058,8 +1671,8 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr  LLRect LLFolderView::getVisibleRect()  { -	S32 visible_height = mScrollContainer->getRect().getHeight(); -	S32 visible_width = mScrollContainer->getRect().getWidth(); +	S32 visible_height = (mScrollContainer ? mScrollContainer->getRect().getHeight() : 0); +	S32 visible_width  = (mScrollContainer ? mScrollContainer->getRect().getWidth()  : 0);  	LLRect visible_rect;  	visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height);  	return visible_rect; @@ -2088,168 +1701,37 @@ void LLFolderView::setShowSingleSelection(BOOL show)  	}  } -void LLFolderView::addItemID(const LLUUID& id, LLFolderViewItem* itemp) -{ -	mItemMap[id] = itemp; -} - -void LLFolderView::removeItemID(const LLUUID& id) -{ -	mItemMap.erase(id); -} - -LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); -LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) -{ -	LLFastTimer _(FTM_GET_ITEM_BY_ID); -	if (id == getListener()->getUUID()) -	{ -		return this; -	} - -	std::map<LLUUID, LLFolderViewItem*>::iterator map_it; -	map_it = mItemMap.find(id); -	if (map_it != mItemMap.end()) -	{ -		return map_it->second; -	} - -	return NULL; -} - -LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id) -{ -	if (id == getListener()->getUUID()) -	{ -		return this; -	} - -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end(); -		 ++iter) -	{ -		LLFolderViewFolder *folder = (*iter); -		if (folder->getListener()->getUUID() == id) -		{ -			return folder; -		} -	} -	return NULL; -} - -bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) -{ -	std::string action = userdata.asString(); -	 -	if ("rename" == action) -	{ -		startRenamingSelectedItem(); -		return true; -	} -	if ("delete" == action) -	{ -		removeSelectedItems(); -		return true; -	} -	if (("copy" == action) || ("cut" == action)) -	{ -		// Clear the clipboard before we start adding things on it -		LLClipboard::instance().reset(); -	} - -	static const std::string change_folder_string = "change_folder_type_"; -	if (action.length() > change_folder_string.length() &&  -		(action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) -	{ -		LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); -		changeType(model, new_folder_type); -		return true; -	} - - -	std::set<LLUUID> selected_items = getSelectionList(); - -	LLMultiPreview* multi_previewp = NULL; -	LLMultiProperties* multi_propertiesp = NULL; - -	if (("task_open" == action  || "open" == action) && selected_items.size() > 1) -	{ -		multi_previewp = new LLMultiPreview(); -		gFloaterView->addChild(multi_previewp); - -		LLFloater::setFloaterHost(multi_previewp); -	 -	} -	else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) -	{ -		multi_propertiesp = new LLMultiProperties(); -		gFloaterView->addChild(multi_propertiesp); - -		LLFloater::setFloaterHost(multi_propertiesp); -	} - -	std::set<LLUUID>::iterator set_iter; - -	for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) -	{ -		LLFolderViewItem* folder_item = getItemByID(*set_iter); -		if(!folder_item) continue; -		LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); -		if(!bridge) continue; -		bridge->performAction(model, action); -	} - -	LLFloater::setFloaterHost(NULL); -	if (multi_previewp) -	{ -		multi_previewp->openFloater(LLSD()); -	} -	else if (multi_propertiesp) -	{ -		multi_propertiesp->openFloater(LLSD()); -	} - -	return true; -} -  static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select");  static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory");  // Main idle routine -void LLFolderView::doIdle() +void LLFolderView::update()  {  	// If this is associated with the user's inventory, don't do anything  	// until that inventory is loaded up. -	const LLInventoryPanel *inventory_panel = dynamic_cast<LLInventoryPanel*>(mParentPanel); -	if (inventory_panel && !inventory_panel->getIsViewsInitialized()) -	{ -		return; -	} -	  	LLFastTimer t2(FTM_INVENTORY); -	BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); -	if (debug_filters != getDebugFilters()) +	if (getFolderViewModel()->getFilter().isModified() && getFolderViewModel()->getFilter().isNotDefault())  	{ -		mDebugFilters = debug_filters; -		arrangeAll(); +		mNeedsAutoSelect = TRUE;  	} -	BOOL filter_modified_and_active = mFilter->isModified() && mFilter->isNotDefault(); -	mNeedsAutoSelect = filter_modified_and_active && -						!(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); -	mFilter->clearModified(); -			  	// filter to determine visibility before arranging -	filterFromRoot(); - +	filter(getFolderViewModel()->getFilter()); +	// Clear the modified setting on the filter only if the filter count is non-zero after running the filter process +	// Note: if the filter count is zero, then the filter most likely halted before completing the entire set of items +	if (getFolderViewModel()->getFilter().isModified() && (getFolderViewModel()->getFilter().getFilterCount() > 0)) +	{ +		getFolderViewModel()->getFilter().clearModified(); +	} +			  	// automatically show matching items, and select first one if we had a selection  	if (mNeedsAutoSelect)  	{  		LLFastTimer t3(FTM_AUTO_SELECT);  		// select new item only if a filtered item not currently selected  		LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); -		if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->potentiallyVisible())) +		if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible()))  		{  			// these are named variables to get around gcc not binding non-const references to rvalues  			// and functor application is inherently non-const to allow for stateful functors @@ -2259,7 +1741,7 @@ void LLFolderView::doIdle()  		// Open filtered folders for folder views with mAutoSelectOverride=TRUE.  		// Used by LLPlacesFolderView. -		if (!mFilter->getFilterSubString().empty()) +		if (getFolderViewModel()->getFilter().showAllResults())  		{  			// these are named variables to get around gcc not binding non-const references to rvalues  			// and functor application is inherently non-const to allow for stateful functors @@ -2270,16 +1752,30 @@ void LLFolderView::doIdle()  		scrollToShowSelection();  	} -	BOOL filter_finished = mCompletedFilterGeneration >= mFilter->getCurrentGeneration()  -						&& !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); +	BOOL filter_finished = getViewModelItem()->passedFilter() +						&& mViewModel->contentsReady();  	if (filter_finished  -		|| gFocusMgr.childHasKeyboardFocus(inventory_panel)  -		|| gFocusMgr.childHasMouseCapture(inventory_panel)) +		|| gFocusMgr.childHasKeyboardFocus(mParentPanel) +		|| gFocusMgr.childHasMouseCapture(mParentPanel))  	{  		// finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process  		mNeedsAutoSelect = FALSE;  	} +  BOOL is_visible = isInVisibleChain(); + +  //Puts folders/items in proper positions +  if ( is_visible ) +  { +    sanitizeSelection(); +    if( needsArrange() ) +    { +      S32 height = 0; +      S32 width = 0; +      S32 total_height = arrange( &width, &height ); +      notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); +    } +  }  	// during filtering process, try to pin selected item's location on screen  	// this will happen when searching your inventory and when new items arrive @@ -2291,22 +1787,30 @@ void LLFolderView::doIdle()  			// lets pin it!  			mPinningSelectedItem = TRUE; -			LLRect visible_content_rect = mScrollContainer->getVisibleContentRect(); +      //Computes visible area  +			const LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect());  			LLFolderViewItem* selected_item = mSelectedItems.back(); +      //Computes location of selected content, content outside visible area will be scrolled to using below code  			LLRect item_rect;  			selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); -			// if item is visible in scrolled region -			if (visible_content_rect.overlaps(item_rect)) +			 +      //Computes intersected region of the selected content and visible area +      LLRect overlap_rect(item_rect); +      overlap_rect.intersectWith(visible_content_rect); + +      //Don't scroll when the selected content exists within the visible area +			if (overlap_rect.getHeight() >= selected_item->getItemHeight())  			{  				// then attempt to keep it in same place on screen  				mScrollConstraintRect = item_rect;  				mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom);  			} +      //Scroll because the selected content is outside the visible area  			else  			{  				// otherwise we just want it onscreen somewhere -				LLRect content_rect = mScrollContainer->getContentWindowRect(); +				LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect());  				mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight());  			}  		} @@ -2329,22 +1833,10 @@ void LLFolderView::doIdle()  	else  	{  		// during normal use (page up/page down, etc), just try to fit item on screen -		LLRect content_rect = mScrollContainer->getContentWindowRect(); +		LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect());  		constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight());  	} - -	BOOL is_visible = isInVisibleChain(); - -	if ( is_visible ) -	{ -		sanitizeSelection(); -		if( needsArrange() ) -		{ -			arrangeFromRoot(); -		} -	} -  	if (mSelectedItems.size() && mNeedsScroll)  	{  		scrollToShowItem(mSelectedItems.back(), constraint_rect); @@ -2365,17 +1857,6 @@ void LLFolderView::doIdle()  	mSignalSelectCallback = FALSE;  } - -//static -void LLFolderView::idle(void* user_data) -{ -	LLFolderView* self = (LLFolderView*)user_data; -	if ( self ) -	{	// Do the real idle  -		self->doIdle(); -	} -} -  void LLFolderView::dumpSelectionInformation()  {  	llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; @@ -2399,7 +1880,7 @@ void LLFolderView::updateRenamerPosition()  		screenPointToLocal( x, y, &x, &y );  		mRenamer->setOrigin( x, y ); -		LLRect scroller_rect(0, 0, gViewerWindow->getWindowWidthScaled(), 0); +		LLRect scroller_rect(0, 0, (S32)LLUI::getWindowSize().mV[VX], 0);  		if (mScrollContainer)  		{  			scroller_rect = mScrollContainer->getContentWindowRect(); @@ -2546,7 +2027,7 @@ void LLFolderView::onRenamerLost()  	if( mRenameItem )  	{ -		setSelectionFromRoot( mRenameItem, TRUE ); +		setSelection( mRenameItem, TRUE );  		mRenameItem = NULL;  	}  } @@ -2570,72 +2051,12 @@ LLFolderViewItem* LLFolderView::getNextUnselectedItem()  	return new_selection;  } -LLInventoryFilter* LLFolderView::getFilter() +S32 LLFolderView::getItemHeight()  { -	return mFilter; -} - -void LLFolderView::setFilterPermMask( PermissionMask filter_perm_mask ) +	if(!hasVisibleChildren())  { -	mFilter->setFilterPermissions(filter_perm_mask); +		//We need to display status textbox, let's reserve some place for it +		return llmax(0, mStatusTextBox->getTextPixelHeight());  } - -U32 LLFolderView::getFilterObjectTypes() const -{ -	return mFilter->getFilterObjectTypes(); -} - -PermissionMask LLFolderView::getFilterPermissions() const -{ -	return mFilter->getFilterPermissions(); -} - -BOOL LLFolderView::isFilterModified() -{ -	return mFilter->isNotDefault(); -} - -void delete_selected_item(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->removeSelectedItems(); -	} -} - -void copy_selected_item(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->copy(); -	} -} - -void paste_items(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->paste(); -	} -} - -void open_selected_items(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->openSelectedItems(); -	} -} - -void properties_selected_items(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->propertiesSelectedItems(); -	} +	return 0;  } diff --git a/indra/newview/llfolderview.h b/indra/llui/llfolderview.h index 3f78312a98..81b0f087e8 100644 --- a/indra/newview/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -39,19 +39,16 @@  #include "lluictrl.h"  #include "v4color.h" -#include "lldarray.h"  #include "stdenums.h"  #include "lldepthstack.h"  #include "lleditmenuhandler.h"  #include "llfontgl.h"  #include "llscrollcontainer.h" -#include "lltooldraganddrop.h" -#include "llviewertexture.h" -class LLFolderViewEventListener; +class LLFolderViewModelInterface;  class LLFolderViewFolder;  class LLFolderViewItem; -class LLInventoryModel; +class LLFolderViewFilter;  class LLPanel;  class LLLineEditor;  class LLMenuGL; @@ -90,13 +87,13 @@ public:  	struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params>  	{  		Mandatory<LLPanel*>	    parent_panel; -		Optional<LLUUID>        task_id;  		Optional<std::string>   title;  		Optional<bool>			use_label_suffix,  								allow_multiselect,  								show_empty_message, -								show_load_status, -								use_ellipses; +								use_ellipses, +								show_item_link_overlays; +		Mandatory<LLFolderViewModelInterface*>	view_model;  		Params();  	}; @@ -108,118 +105,90 @@ public:  	virtual BOOL canFocusChildren() const; +	virtual const LLFolderView*	getRoot() const { return this; }  	virtual LLFolderView*	getRoot() { return this; } -	// FolderViews default to sort by name. This will change that, -	// and resort the items if necessary. -	void setSortOrder(U32 order); -	void setFilterPermMask(PermissionMask filter_perm_mask); -	 +	LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } +	const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } +  	typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t;  	void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); }  	void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } -	// filter is never null -	LLInventoryFilter* getFilter(); -	const std::string getFilterSubString(BOOL trim = FALSE); -	U32 getFilterObjectTypes() const; -	PermissionMask getFilterPermissions() const; -	// *NOTE: use getFilter()->getShowFolderState(); -	//LLInventoryFilter::EFolderShow getShowFolderState(); -	U32 getSortOrder() const; -	BOOL isFilterModified(); -  	bool getAllowMultiSelect() { return mAllowMultiSelect; }  	// Close all folders in the view  	void closeAllFolders();  	void openTopLevelFolders(); -	virtual void toggleOpen() {}; -	virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse); -	virtual BOOL addFolder( LLFolderViewFolder* folder); +	virtual void addFolder( LLFolderViewFolder* folder);  	// Find width and height of this object and its children. Also  	// makes sure that this view and its children are the right size. -	virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); +	virtual S32 arrange( S32* width, S32* height ); +	virtual S32 getItemHeight();  	void arrangeAll() { mArrangeGeneration++; }  	S32 getArrangeGeneration() { return mArrangeGeneration; } -	// Apply filters to control visibility of inventory items -	virtual void filter( LLInventoryFilter& filter); +	// applies filters to control visibility of items +	virtual void filter( LLFolderViewFilter& filter);  	// Get the last selected item  	virtual LLFolderViewItem* getCurSelectedItem( void );  	// Record the selected item and pass it down the hierarchy.  	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, -		BOOL take_keyboard_focus); +		BOOL take_keyboard_focus = TRUE); -	// Used by menu callbacks -	void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); - -	// Called once a frame to update the selection if mSelectThisID has been set -	void updateSelection(); - -	// This method is used to toggle the selection of an item.  -	// Walks children and keeps track of selected objects. +	// This method is used to toggle the selection of an item. Walks +	// children, and keeps track of selected objects.  	virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); -	virtual std::set<LLUUID> getSelectionList() const; +	virtual std::set<LLFolderViewItem*> getSelectionList() const; +	S32 getNumSelectedItems() { return mSelectedItems.size(); } -	// Make sure if ancestor is selected, descendents are not +	// Make sure if ancestor is selected, descendants are not  	void sanitizeSelection(); -	void clearSelection(); +	virtual void clearSelection();  	void addToSelectionList(LLFolderViewItem* item);  	void removeFromSelectionList(LLFolderViewItem* item); -	BOOL startDrag(LLToolDragAndDrop::ESource source); +	bool startDrag();  	void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; }  	void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; }  	LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; }  	// Deletion functionality   	void removeSelectedItems(); - 	static void removeCutItems();  	// Open the selected item  	void openSelectedItems( void );  	void propertiesSelectedItems( void ); -	// Change the folder type -	void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type); -  	void autoOpenItem(LLFolderViewFolder* item);  	void closeAutoOpenedFolders();  	BOOL autoOpenTest(LLFolderViewFolder* item); +	BOOL isOpen() const { return TRUE; } // root folder always open  	// Copy & paste -	virtual void	copy();  	virtual BOOL	canCopy() const; +	virtual void	copy(); -	virtual void	cut();  	virtual BOOL	canCut() const; +	virtual void	cut(); -	virtual void	paste();  	virtual BOOL	canPaste() const; +	virtual void	paste(); -	virtual void	doDelete();  	virtual BOOL	canDoDelete() const; +	virtual void	doDelete();  	LLFolderViewItem* getNextUnselectedItem(); -	 +  	// Public rename functionality - can only start the process  	void startRenamingSelectedItem( void ); -	// These functions were used when there was only one folderview, -	// and relied on that concept. This functionality is now handled -	// by the listeners and the lldraganddroptool. -	//LLFolderViewItem*	getMovingItem() { return mMovingItem; } -	//void setMovingItem( LLFolderViewItem* item ) { mMovingItem = item; } -	//void				dragItemIntoFolder( LLFolderViewItem* moving_item, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); -	//void				dragFolderIntoFolder( LLFolderViewFolder* moving_folder, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); -  	// LLView functionality  	///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent );  	/*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); @@ -250,16 +219,9 @@ public:  	BOOL getShowSingleSelection() { return mShowSingleSelection; }  	F32  getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }  	bool getUseEllipses() { return mUseEllipses; } +	S32 getSelectedCount() { return (S32)mSelectedItems.size(); } -	void addItemID(const LLUUID& id, LLFolderViewItem* itemp); -	void removeItemID(const LLUUID& id); -	LLFolderViewItem* getItemByID(const LLUUID& id); -	LLFolderViewFolder* getFolderByID(const LLUUID& id); -	 -	bool doToSelected(LLInventoryModel* model, const LLSD& userdata); -	 -	void	doIdle();						// Real idle routine -	static void idle(void* user_data);		// static glue to doIdle() +	void	update();						// needs to be called periodically (e.g. once per frame)  	BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; }  	BOOL needsAutoRename() { return mNeedsAutoRename; } @@ -267,9 +229,9 @@ public:  	void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; }  	void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } -	void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } +	bool showItemLinkOverlays() { return mShowItemLinkOverlays; } -	BOOL getDebugFilters() { return mDebugFilters; } +	void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }  	LLPanel* getParentPanel() { return mParentPanel; }  	// DEBUG only @@ -298,7 +260,6 @@ protected:  	BOOL addNoOptions(LLMenuGL* menu) const; -	void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response);  protected:  	LLHandle<LLView>					mPopupMenuHandle; @@ -309,7 +270,6 @@ protected:  	BOOL							mAllowMultiSelect;  	BOOL							mShowEmptyMessage;  	BOOL							mShowFolderHierarchy; -	LLUUID							mSourceID;  	// Renaming variables and methods  	LLFolderViewItem*				mRenameItem;  // The item currently being renamed @@ -322,15 +282,13 @@ protected:  	BOOL							mAutoSelectOverride;  	BOOL							mNeedsAutoRename;  	bool							mUseLabelSuffix; +	bool							mShowItemLinkOverlays; -	BOOL							mDebugFilters; -	U32								mSortOrder;  	LLDepthStack<LLFolderViewFolder>	mAutoOpenItems;  	LLFolderViewFolder*				mAutoOpenCandidate;  	LLFrameTimer					mAutoOpenTimer;  	LLFrameTimer					mSearchTimer;  	std::string						mSearchString; -	LLInventoryFilter*				mFilter;  	BOOL							mShowSelectionContext;  	BOOL							mShowSingleSelection;  	LLFrameTimer					mMultiSelectionFadeTimer; @@ -340,13 +298,11 @@ protected:  	signal_t						mReshapeSignal;  	S32								mSignalSelectCallback;  	S32								mMinWidth; -	S32								mRunningHeight; -	std::map<LLUUID, LLFolderViewItem*> mItemMap;  	BOOL							mDragAndDropThisFrame; -	LLUUID							mSelectThisID; // if non null, select this item -	  	LLPanel*						mParentPanel; +	 +	LLFolderViewModelInterface*		mViewModel;  	/**  	 * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. @@ -367,8 +323,66 @@ public:  }; -bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b); -bool sort_item_date(LLFolderViewItem* a, LLFolderViewItem* b); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewFunctor +// +// Simple abstract base class for applying a functor to folders and +// items in a folder view hierarchy. This is suboptimal for algorithms +// that only work folders or only work on items, but I'll worry about +// that later when it's determined to be too slow. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFolderViewFunctor +{ +public: +	virtual ~LLFolderViewFunctor() {} +	virtual void doFolder(LLFolderViewFolder* folder) = 0; +	virtual void doItem(LLFolderViewItem* item) = 0; +}; + +class LLSelectFirstFilteredItem : public LLFolderViewFunctor +{ +public: +	LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} +	virtual ~LLSelectFirstFilteredItem() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item); +	BOOL wasItemSelected() { return mItemSelected; } +protected: +	BOOL mItemSelected; +}; + +class LLOpenFilteredFolders : public LLFolderViewFunctor +{ +public: +	LLOpenFilteredFolders()  {} +	virtual ~LLOpenFilteredFolders() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item); +}; + +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: +	LLSaveFolderState() : mApply(FALSE) {} +	virtual ~LLSaveFolderState() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item) {} +	void setApply(BOOL apply); +	void clearOpenFolders() { mOpenFolders.clear(); } +protected: +	std::set<LLUUID> mOpenFolders; +	BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: +	LLOpenFoldersWithSelection() {} +	virtual ~LLOpenFoldersWithSelection() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item); +};  // Flags for buildContextMenu()  const U32 SUPPRESS_OPEN_ITEM = 0x1; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 3aa16b4413..52923389cd 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -23,26 +23,17 @@  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA  * $/LicenseInfo$  */ -#include "llviewerprecompiledheaders.h" - +#include "linden_common.h"  #include "llfolderviewitem.h" -// viewer includes -#include "llfolderview.h"		// Items depend extensively on LLFolderViews -#include "llfoldervieweventlistener.h" -#include "llviewerfoldertype.h" -#include "llinventorybridge.h"	// for LLItemBridge in LLInventorySort::operator() -#include "llinventoryfilter.h" -#include "llinventoryfunctions.h" -#include "llinventorymodelbackgroundfetch.h" +#include "llfolderview.h" +#include "llfolderviewmodel.h"  #include "llpanel.h" -#include "llviewercontrol.h"	// gSavedSettings -#include "llviewerwindow.h"		// Argh, only for setCursor() - -// linden library includes +#include "llcriticaldamp.h"  #include "llclipboard.h"  #include "llfocusmgr.h"		// gFocusMgr  #include "lltrans.h" +#include "llwindow.h"  ///----------------------------------------------------------------------------  /// Class LLFolderViewItem @@ -91,17 +82,15 @@ void LLFolderViewItem::cleanupClass()  // NOTE: Optimize this, we call it a *lot* when opening a large inventory  LLFolderViewItem::Params::Params() -:	icon(), -	icon_open(), -	icon_overlay(), -	root(), +:	root(),  	listener(),  	folder_arrow_image("folder_arrow_image"),  	folder_indentation("folder_indentation"),  	selection_image("selection_image"),  	item_height("item_height"),  	item_top_pad("item_top_pad"), -	creation_date() +	creation_date(), +	allow_open("allow_open", true)  {}  // Default constructor @@ -117,22 +106,18 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)  	mHasVisibleChildren(FALSE),  	mIndentation(0),  	mItemHeight(p.item_height), -	mPassedFilter(FALSE), -	mLastFilterGeneration(-1), -	mStringMatchOffset(std::string::npos),  	mControlLabelRotation(0.f),  	mDragAndDropTarget(FALSE), -	mIsLoading(FALSE),  	mLabel(p.name),  	mRoot(p.root), -	mCreationDate(p.creation_date), -	mIcon(p.icon), -	mIconOpen(p.icon_open), -	mIconOverlay(p.icon_overlay), -	mListener(p.listener), -	mShowLoadStatus(false), -	mIsMouseOverTitle(false) +	mViewModelItem(p.listener), +	mIsMouseOverTitle(false), +	mAllowOpen(p.allow_open)  { +	if (mViewModelItem) +	{ +		mViewModelItem->setFolderViewItem(this); +}  }  BOOL LLFolderViewItem::postBuild() @@ -144,8 +129,8 @@ BOOL LLFolderViewItem::postBuild()  // Destroys the object  LLFolderViewItem::~LLFolderViewItem( void )  { -	delete mListener; -	mListener = NULL; +	delete mViewModelItem; +	mViewModelItem = NULL;  }  LLFolderView* LLFolderViewItem::getRoot() @@ -153,6 +138,10 @@ LLFolderView* LLFolderViewItem::getRoot()  	return mRoot;  } +const LLFolderView* LLFolderViewItem::getRoot() const +{ +	return mRoot; +}  // Returns true if this object is a child (or grandchild, etc.) of potential_ancestor.  BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor )  { @@ -214,146 +203,47 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)  	return itemp;  } -// is this item something we think we should be showing? -// for example, if we haven't gotten around to filtering it yet, then the answer is yes -// until we find out otherwise -BOOL LLFolderViewItem::potentiallyVisible() -{ -	// we haven't been checked against min required filter -	// or we have and we passed -	return potentiallyFiltered(); -} - -BOOL LLFolderViewItem::potentiallyFiltered() -{ -	return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); -} - -BOOL LLFolderViewItem::getFiltered()  -{  -	return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration();  -} - -BOOL LLFolderViewItem::getFiltered(S32 filter_generation)  +BOOL LLFolderViewItem::passedFilter(S32 filter_generation)   { -	return mPassedFilter && mLastFilterGeneration >= filter_generation; +	return getViewModelItem()->passedFilter(filter_generation);  } -void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation) -{ -	mPassedFilter = filtered; -	mLastFilterGeneration = filter_generation; -} - -void LLFolderViewItem::setIcon(LLUIImagePtr icon) +void LLFolderViewItem::refresh()  { -	mIcon = icon; -} +	LLFolderViewModelItem& vmi = *getViewModelItem(); -// refresh information from the listener -void LLFolderViewItem::refreshFromListener() -{ -	if(mListener) -	{ -		mLabel = mListener->getDisplayName(); -		LLFolderType::EType preferred_type = mListener->getPreferredType(); +	mLabel = vmi.getDisplayName(); -		// *TODO: to be removed when database supports multi language. This is a -		// temporary attempt to display the inventory folder in the user locale. -		// mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID -		//		it uses the same way to find localized string +	setToolTip(mLabel); +	mIcon = vmi.getIcon(); +	mIconOpen = vmi.getIconOpen(); +	mIconOverlay = vmi.getIconOverlay(); -		// HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) -		// Translation of Accessories folder in Library inventory folder -		bool accessories = false; -		if(mLabel == std::string("Accessories")) -		{ -			//To ensure that Accessories folder is in Library we have to check its parent folder. -			//Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model -			LLInventoryCategory* cat = gInventory.getCategory(mListener->getUUID()); -			if(cat) -			{ -				const LLUUID& parent_folder_id = cat->getParentUUID(); -				accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); -			} -		} - -		//"Accessories" inventory category has folder type FT_NONE. So, this folder -		//can not be detected as protected with LLFolderType::lookupIsProtectedType -		if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) -		{ -			LLTrans::findString(mLabel, "InvFolder " + mLabel); -		}; - -		setToolTip(mLabel); -		setIcon(mListener->getIcon()); -		time_t creation_date = mListener->getCreationDate(); -		if ((creation_date > 0) && (mCreationDate != creation_date)) -		{ -			setCreationDate(creation_date); -			dirtyFilter(); -		}  		if (mRoot->useLabelSuffix())  		{ -			mLabelStyle = mListener->getLabelStyle(); -			mLabelSuffix = mListener->getLabelSuffix(); -		} -	} +		mLabelStyle = vmi.getLabelStyle(); +		mLabelSuffix = vmi.getLabelSuffix();  } -void LLFolderViewItem::refresh() -{ -	refreshFromListener(); +	//TODO RN: make sure this logic still fires +	//std::string searchable_label(mLabel); +	//searchable_label.append(mLabelSuffix); +	//LLStringUtil::toUpper(searchable_label); -	std::string searchable_label(mLabel); -	searchable_label.append(mLabelSuffix); -	LLStringUtil::toUpper(searchable_label); - -	if (mSearchableLabel.compare(searchable_label)) -	{ -		mSearchableLabel.assign(searchable_label); -		dirtyFilter(); -		// some part of label has changed, so overall width has potentially changed, and sort order too -		if (mParentFolder) -		{ -			mParentFolder->requestSort(); -			mParentFolder->requestArrange(); -		} -	} +	//if (mSearchableLabel.compare(searchable_label)) +	//{ +	//	mSearchableLabel.assign(searchable_label); +	//	vmi.dirtyFilter(); +	//	// some part of label has changed, so overall width has potentially changed, and sort order too +	//	if (mParentFolder) +	//	{ +	//		mParentFolder->requestSort(); +	//		mParentFolder->requestArrange(); +	//	} +	//}  	mLabelWidthDirty = true; -} - -void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ -	functor(mListener); -} - -// This function is called when items are added or view filters change. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::filterFromRoot( void ) -{ -	LLFolderViewItem* root = getRoot(); - -	root->filter(*((LLFolderView*)root)->getFilter()); -} - -// This function is called when the folder view is dirty. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::arrangeFromRoot() -{ -	LLFolderViewItem* root = getRoot(); - -	S32 height = 0; -	S32 width = 0; -	S32 total_height = root->arrange( &width, &height, 0 ); - -	LLSD params; -	params["action"] = "size_changes"; -	params["height"] = total_height; -	getParent()->notifyParent(params); +	vmi.dirtyFilter();  }  // Utility function for LLFolderView @@ -367,7 +257,7 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection,  	}  	if(set_selection)  	{ -		setSelectionFromRoot(this, TRUE, take_keyboard_focus); +		getRoot()->setSelection(this, TRUE, take_keyboard_focus);  		if(root)  		{  			root->scrollToShowSelection(); @@ -375,57 +265,29 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection,  	}		  } -// This function clears the currently selected item, and records the -// specified selected item appropriately for display and use in the -// UI. If open is TRUE, then folders are opened up along the way to -// the selection. -void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, -											BOOL openitem, -											BOOL take_keyboard_focus) -{ -	getRoot()->setSelection(selection, openitem, take_keyboard_focus); -} - -// helper function to change the selection from the root. -void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) -{ -	getRoot()->changeSelection(selection, selected); -} -std::set<LLUUID> LLFolderViewItem::getSelectionList() const +std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const  { -	std::set<LLUUID> selection; +	std::set<LLFolderViewItem*> selection;  	return selection;  } -EInventorySortGroup LLFolderViewItem::getSortGroup()  const -{  -	return SG_ITEM;  -} -  // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder)  { -	if (!folder) -	{ -		return FALSE; -	} -	mParentFolder = folder; -	root->addItemID(getListener()->getUUID(), this); -	return folder->addItem(this); +	folder->addItem(this);  }  // Finds width and height of this object and its children.  Also  // makes sure that this view and its children are the right size. -S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) +S32 LLFolderViewItem::arrange( S32* width, S32* height )  {  	const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();  	S32 indentation = p.folder_indentation();  	// Only indent deeper items in hierarchy -	mIndentation = (getParentFolder()  -					&& getParentFolder()->getParentFolder() ) -		? mParentFolder->getIndentation() + indentation +	mIndentation = (getParentFolder()) +		? getParentFolder()->getIndentation() + indentation  		: 0;  	if (mLabelWidthDirty)  	{ @@ -451,40 +313,6 @@ S32 LLFolderViewItem::getItemHeight()  	return mItemHeight;  } -void LLFolderViewItem::filter( LLInventoryFilter& filter) -{ -	const BOOL previous_passed_filter = mPassedFilter; -	const BOOL passed_filter = filter.check(this); - -	// If our visibility will change as a result of this filter, then -	// we need to be rearranged in our parent folder -	if (mParentFolder) -	{ -		if (getVisible() != passed_filter -			||	previous_passed_filter != passed_filter ) -			mParentFolder->requestArrange(); -	} - -	setFiltered(passed_filter, filter.getCurrentGeneration()); -	mStringMatchOffset = filter.getStringMatchOffset(); -	filter.decrementFilterCount(); - -	if (getRoot()->getDebugFilters()) -	{ -		mStatusText = llformat("%d", mLastFilterGeneration); -	} -} - -void LLFolderViewItem::dirtyFilter() -{ -	mLastFilterGeneration = -1; -	// bubble up dirty flag all the way to root -	if (getParentFolder()) -	{ -		getParentFolder()->setCompletedFilterGeneration(-1, TRUE); -	} -} -  // *TODO: This can be optimized a lot by simply recording that it is  // selected in the appropriate places, and assuming that set selection  // means 'deselect' for a leaf item. Do this optimization after @@ -529,45 +357,31 @@ void LLFolderViewItem::selectItem(void)  {  	if (mIsSelected == FALSE)  	{ -		if (mListener) -		{ -			mListener->selectItem(); -		} +		getViewModelItem()->selectItem();  		mIsSelected = TRUE;  	}  }  BOOL LLFolderViewItem::isMovable()  { -	if( mListener ) -	{ -		return mListener->isItemMovable(); +	return getViewModelItem()->isItemMovable();  	} -	else -	{ -		return TRUE; -	} -}  BOOL LLFolderViewItem::isRemovable()  { -	if( mListener ) -	{ -		return mListener->isItemRemovable(); -	} -	else -	{ -		return TRUE; -	} +	return getViewModelItem()->isItemRemovable();  }  void LLFolderViewItem::destroyView()  { +	getRoot()->removeFromSelectionList(this); +  	if (mParentFolder)  	{  		// removeView deletes me -		mParentFolder->removeView(this); +		mParentFolder->extractItem(this);  	} +	delete this;  }  // Call through to the viewed object and return true if it can be @@ -579,35 +393,20 @@ BOOL LLFolderViewItem::remove()  	{  		return FALSE;  	} -	if(mListener) -	{ -		return mListener->removeItem(); +	return getViewModelItem()->removeItem();  	} -	return TRUE; -}  // Build an appropriate context menu for the item.  void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags)  { -	if(mListener) -	{ -		mListener->buildContextMenu(menu, flags); +	getViewModelItem()->buildContextMenu(menu, flags);  	} -}  void LLFolderViewItem::openItem( void )  { -	if( mListener ) +	if (mAllowOpen)  	{ -		mListener->openItem(); -	} -} - -void LLFolderViewItem::preview( void ) -{ -	if (mListener) -	{ -		mListener->previewItem(); +	getViewModelItem()->openItem();  	}  } @@ -615,44 +414,21 @@ void LLFolderViewItem::rename(const std::string& new_name)  {  	if( !new_name.empty() )  	{ -		if( mListener ) -		{ -			mListener->renameItem(new_name); - -			if(mParentFolder) -			{ -				mParentFolder->requestSort(); -			} -		} +		getViewModelItem()->renameItem(new_name);  	}  } -const std::string& LLFolderViewItem::getSearchableLabel() const -{ -	return mSearchableLabel; -} - -LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void) -{ -	if (!getListener()) return NULL; -	return gInventory.getItem(getListener()->getUUID()); -} -  const std::string& LLFolderViewItem::getName( void ) const  { -	if(mListener) -	{ -		return mListener->getName(); +	return getViewModelItem()->getName();  	} -	return mLabel; -}  // LLView functionality  BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask )  {  	if(!mIsSelected)  	{ -		setSelectionFromRoot(this, FALSE); +		getRoot()->setSelection(this, FALSE);  	}  	make_ui_sound("UISndClick");  	return TRUE; @@ -673,7 +449,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )  	{  		if(mask & MASK_CONTROL)  		{ -			changeSelectionFromRoot(this, !mIsSelected); +			getRoot()->changeSelection(this, !mIsSelected);  		}  		else if (mask & MASK_SHIFT)  		{ @@ -681,7 +457,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )  		}  		else  		{ -			setSelectionFromRoot(this, FALSE); +			getRoot()->setSelection(this, FALSE);  		}  		make_ui_sound("UISndClick");  	} @@ -690,51 +466,25 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )  		mSelectPending = TRUE;  	} -	if( isMovable() ) -	{ -		S32 screen_x; -		S32 screen_y; -		localPointToScreen(x, y, &screen_x, &screen_y ); -		LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y ); -	} +	mDragStartX = x; +	mDragStartY = y;  	return TRUE;  }  BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )  { +	static LLCachedControl<S32> drag_and_drop_threshold(*LLUI::sSettingGroups["config"],"DragAndDropDistanceThreshold"); +  	mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight));  	if( hasMouseCapture() && isMovable() )  	{ -		S32 screen_x; -		S32 screen_y; -		localPointToScreen(x, y, &screen_x, &screen_y ); -		BOOL can_drag = TRUE; -		if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) -		{  			LLFolderView* root = getRoot(); -			if(root->getCurSelectedItem()) +		if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold()  +			&& root->getCurSelectedItem() +			&& root->startDrag())  			{ -				LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_WORLD; - -				// *TODO: push this into listener and remove -				// dependency on llagent -				if (mListener -					&& gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getRootFolderID())) -				{ -					src = LLToolDragAndDrop::SOURCE_AGENT; -				} -				else if (mListener -					&& gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getLibraryRootFolderID())) -				{ -					src = LLToolDragAndDrop::SOURCE_LIBRARY; -				} - -				can_drag = root->startDrag(src); -				if (can_drag) -				{ -					// if (mListener) mListener->startDrag();  					// RN: when starting drag and drop, clear out last auto-open  					root->autoOpenTest(NULL);  					root->setShowSelectionContext(TRUE); @@ -744,25 +494,19 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )  					// item.  					gFocusMgr.setKeyboardFocus(NULL); -					return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); +			getWindow()->setCursor(UI_CURSOR_ARROW); +			return TRUE;  				} -			} -		} - -		if (can_drag) -		{ -			gViewerWindow->setCursor(UI_CURSOR_ARROW); -		}  		else  		{ -			gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); +			getWindow()->setCursor(UI_CURSOR_NOLOCKED); +			return TRUE;  		} -		return TRUE;  	}  	else  	{  		getRoot()->setShowSelectionContext(FALSE); -		gViewerWindow->setCursor(UI_CURSOR_ARROW); +		getWindow()->setCursor(UI_CURSOR_ARROW);  		// let parent handle this then...  		return FALSE;  	} @@ -771,7 +515,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )  BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask )  { -	preview(); +	openItem();  	return TRUE;  } @@ -788,7 +532,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )  		//...then select  		if(mask & MASK_CONTROL)  		{ -			changeSelectionFromRoot(this, !mIsSelected); +			getRoot()->changeSelection(this, !mIsSelected);  		}  		else if (mask & MASK_SHIFT)  		{ @@ -796,7 +540,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )  		}  		else  		{ -			setSelectionFromRoot(this, FALSE); +			getRoot()->setSelection(this, FALSE);  		}  	} @@ -804,7 +548,10 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )  	if( hasMouseCapture() )  	{ +		if (getRoot()) +		{  		getRoot()->setShowSelectionContext(FALSE); +		}  		gFocusMgr.setMouseCapture( NULL );  	}  	return TRUE; @@ -821,11 +568,8 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  										 EAcceptance* accept,  										 std::string& tooltip_msg)  { -	BOOL accepted = FALSE;  	BOOL handled = FALSE; -	if(mListener) -	{ -		accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); +	BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg);  		handled = accepted;  		if (accepted)  		{ @@ -836,7 +580,6 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  		{  			*accept = ACCEPT_NO;  		} -	}  	if(mParentFolder && !handled)  	{  		// store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. @@ -871,16 +614,12 @@ void LLFolderViewItem::draw()  	const S32 FOCUS_LEFT = 1;  	const LLFontGL* font = getLabelFontForStyle(mLabelStyle); -	const BOOL in_inventory = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getRootFolderID()); -	const BOOL in_library = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getLibraryRootFolderID()); +	getViewModelItem()->update();  	//--------------------------------------------------------------------------------//  	// Draw open folder arrow  	// -	const bool up_to_date = mListener && mListener->isUpToDate(); -	const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) // we fetched our children and some of them have passed the filter... -										|| (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter) -	if (possibly_has_children) +	if (hasVisibleChildren() || getViewModelItem()->hasChildren())  	{  		LLUIImage* arrow_image = default_params.folder_arrow_image;  		gl_draw_scaled_rotated_image( @@ -892,8 +631,8 @@ void LLFolderViewItem::draw()  	//--------------------------------------------------------------------------------//  	// Draw highlight for selected items  	// -	const BOOL show_context = getRoot()->getShowSelectionContext(); -	const BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus()); // If we have keyboard focus, draw selection filled +	const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); +	const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled  	const S32 focus_top = getRect().getHeight();  	const S32 focus_bottom = getRect().getHeight() - mItemHeight;  	const bool folder_open = (getRect().getHeight() > mItemHeight + 4); @@ -904,8 +643,8 @@ void LLFolderViewItem::draw()  		if (!mIsCurSelection)  		{  			// do time-based fade of extra objects -			F32 fade_time = getRoot()->getSelectionFadeElapsedTime(); -			if (getRoot()->getShowSingleSelection()) +			F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); +			if (getRoot() && getRoot()->getShowSingleSelection())  			{  				// fading out  				bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); @@ -977,8 +716,6 @@ void LLFolderViewItem::draw()  		mDragAndDropTarget = FALSE;  	} -	const LLViewerInventoryItem *item = getInventoryItem(); -	const BOOL highlight_link = mIconOverlay && item && item->getIsLinkType();  	//--------------------------------------------------------------------------------//  	// Draw open icon  	// @@ -992,7 +729,7 @@ void LLFolderViewItem::draw()   		mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1);   	} -	if (highlight_link) +	if (mIconOverlay && getRoot()->showItemLinkOverlays())  	{  		mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1);  	} @@ -1005,31 +742,29 @@ void LLFolderViewItem::draw()  		return;  	} -	LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; -	if (highlight_link) color = sLinkColor; -	if (in_library) color = sLibraryColor; -	 +	std::string::size_type filter_string_length = mViewModelItem->hasFilterStringMatch() ? mViewModelItem->getFilterStringSize() : 0;  	F32 right_x  = 0;  	F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD;  	F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); +	std::string combined_string = mLabel + mLabelSuffix; -	//--------------------------------------------------------------------------------// -	// Highlight filtered text -	// -	if (getRoot()->getDebugFilters()) +	if (filter_string_length > 0)  	{ -		if (!getFiltered() && !possibly_has_children) -		{ -			color.mV[VALPHA] *= 0.5f; +		S32 left = llround(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 2; +		S32 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2; +		S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); +		S32 top = getRect().getHeight() - TOP_PAD; + +		LLUIImage* box_image = default_params.selection_image; +		LLRect box_rect(left, top, right, bottom); +		box_image->draw(box_rect, sFilterBGColor);  		} -		LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ?  -			LLColor4(0.5f, 0.8f, 0.5f, 1.f) :  -			LLColor4(0.8f, 0.5f, 0.5f, 1.f); -		LLFontGL::getFontMonospace()->renderUTF8(mStatusText, 0, text_left, y, filter_color, -												 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -												 S32_MAX, S32_MAX, &right_x, FALSE ); -		text_left = right_x; -	} + +	LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; +	//TODO RN: implement this in terms of getColor() +	//if (highlight_link) color = sLinkColor; +	//if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; +	  	//--------------------------------------------------------------------------------//  	// Draw the actual label text  	// @@ -1038,30 +773,6 @@ void LLFolderViewItem::draw()  					 S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE);  	//--------------------------------------------------------------------------------// -	// Draw "Loading..." text -	// -	bool root_is_loading = false; -	if (in_inventory) -	{ -		root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress();  -	} -	if (in_library) -	{ -		root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); -	} -	if ((mIsLoading -		&&	mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) -			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive() -				&&	root_is_loading -				&&	mShowLoadStatus)) -	{ -		std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) "; -		font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor, -						 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,  -						 S32_MAX, S32_MAX, &right_x, FALSE); -	} - -	//--------------------------------------------------------------------------------//  	// Draw label suffix  	//  	if (!mLabelSuffix.empty()) @@ -1074,28 +785,24 @@ void LLFolderViewItem::draw()  	//--------------------------------------------------------------------------------//  	// Highlight string match  	// -	if (mStringMatchOffset != std::string::npos) -	{ -		// don't draw backgrounds for zero-length strings -		S32 filter_string_length = getRoot()->getFilterSubString().size();  		if (filter_string_length > 0)  		{ -			std::string combined_string = mLabel + mLabelSuffix; -			S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; -			S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; -			S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); -			S32 top = getRect().getHeight() - TOP_PAD; -		 -			LLUIImage* box_image = default_params.selection_image; -			LLRect box_rect(left, top, right, bottom); -			box_image->draw(box_rect, sFilterBGColor); -			F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); +		F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset());  			F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; -			font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, +		font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy,  							  sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,  							  filter_string_length, S32_MAX, &right_x, FALSE );  		}  	} + +const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const +{ +	return getRoot()->getFolderViewModel(); +} + +LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) +{ +	return getRoot()->getFolderViewModel();  }  bool LLFolderViewItem::isInSelection() const @@ -1103,25 +810,21 @@ bool LLFolderViewItem::isInSelection() const  	return mIsSelected || (mParentFolder && mParentFolder->isInSelection());  } + +  ///----------------------------------------------------------------------------  /// Class LLFolderViewFolder  ///----------------------------------------------------------------------------  LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):  -	LLFolderViewItem( p ),	// 0 = no create time +	LLFolderViewItem( p ),  	mIsOpen(FALSE),  	mExpanderHighlighted(FALSE),  	mCurHeight(0.f),  	mTargetHeight(0.f),  	mAutoOpenCountdown(0.f), -	mSubtreeCreationDate(0), -	mAmTrash(LLFolderViewFolder::UNKNOWN),  	mLastArrangeGeneration( -1 ), -	mLastCalculatedWidth(0), -	mCompletedFilterGeneration(-1), -	mMostFilteredDescendantGeneration(-1), -	mNeedsSort(false), -	mPassedFolderFilter(FALSE) +	mLastCalculatedWidth(0)  {  } @@ -1133,44 +836,26 @@ LLFolderViewFolder::~LLFolderViewFolder( void )  	gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()  } -void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation) -{ -	mPassedFolderFilter = filtered; -	mLastFilterGeneration = filter_generation; -} - -bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation) -{ -	return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); -} -  // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)  { -	if (!folder) -	{ -		return FALSE; -	} -	mParentFolder = folder; -	root->addItemID(getListener()->getUUID(), this); -	return folder->addFolder(this); +	folder->addFolder(this);  } +static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); +  // Finds width and height of this object and its children. Also  // makes sure that this view and its children are the right size. -S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) +S32 LLFolderViewFolder::arrange( S32* width, S32* height )  {  	// sort before laying out contents -	if (mNeedsSort) -	{ -		mFolders.sort(mSortFunction); -		mItems.sort(mSortFunction); -		mNeedsSort = false; -	} +	getRoot()->getFolderViewModel()->sort(this); + +	LLFastTimer t2(FTM_ARRANGE);  	// evaluate mHasVisibleChildren  	mHasVisibleChildren = false; -	if (hasFilteredDescendants(filter_generation)) +	if (getViewModelItem()->descendantsPassedFilter())  	{  		// We have to verify that there's at least one child that's not filtered out  		bool found = false; @@ -1178,7 +863,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  		for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit)  		{  			LLFolderViewItem* itemp = (*iit); -			found = (itemp->getFiltered(filter_generation)); +			found = itemp->passedFilter();  			if (found)  				break;  		} @@ -1188,10 +873,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  			for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit)  			{  				LLFolderViewFolder* folderp = (*fit); -				found = ( folderp->getListener() -								&&	(folderp->getFiltered(filter_generation) -									 ||	(folderp->getFilteredFolder(filter_generation)  -										 && folderp->hasFilteredDescendants(filter_generation)))); +				found = folderp->passedFilter();  				if (found)  					break;  			} @@ -1201,13 +883,12 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  	}  	// calculate height as a single item (without any children), and reshapes rectangle to match -	LLFolderViewItem::arrange( width, height, filter_generation ); +	LLFolderViewItem::arrange( width, height );  	// clamp existing animated height so as to never get smaller than a single item  	mCurHeight = llmax((F32)*height, mCurHeight);  	// initialize running height value as height of single item in case we have no children -	*height = getItemHeight();  	F32 running_height = (F32)*height;  	F32 target_height = (F32)*height; @@ -1217,7 +898,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  		// set last arrange generation first, in case children are animating  		// and need to be arranged again  		mLastArrangeGeneration = getRoot()->getArrangeGeneration(); -		if (mIsOpen) +		if (isOpen())  		{  			// Add sizes of children  			S32 parent_item_height = getRect().getHeight(); @@ -1225,17 +906,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  			for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit)  			{  				LLFolderViewFolder* folderp = (*fit); -				if (getRoot()->getDebugFilters()) -				{ -					folderp->setVisible(TRUE); -				} -				else -				{ -					folderp->setVisible( folderp->getListener() -										&&	(folderp->getFiltered(filter_generation) -											||	(folderp->getFilteredFolder(filter_generation)  -												&& folderp->hasFilteredDescendants(filter_generation)))); // passed filter or has descendants that passed filter -				} +				folderp->setVisible(folderp->passedFilter()); // passed filter or has descendants that passed filter  				if (folderp->getVisible())  				{ @@ -1243,7 +914,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  					S32 child_height = 0;  					S32 child_top = parent_item_height - llround(running_height); -					target_height += folderp->arrange( &child_width, &child_height, filter_generation ); +					target_height += folderp->arrange( &child_width, &child_height );  					running_height += (F32)child_height;  					*width = llmax(*width, child_width); @@ -1254,14 +925,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  				iit != mItems.end(); ++iit)  			{  				LLFolderViewItem* itemp = (*iit); -				if (getRoot()->getDebugFilters()) -				{ -					itemp->setVisible(TRUE); -				} -				else -				{ -					itemp->setVisible(itemp->getFiltered(filter_generation)); -				} +				itemp->setVisible(itemp->passedFilter());  				if (itemp->getVisible())  				{ @@ -1269,7 +933,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  					S32 child_height = 0;  					S32 child_top = parent_item_height - llround(running_height); -					target_height += itemp->arrange( &child_width, &child_height, filter_generation ); +					target_height += itemp->arrange( &child_width, &child_height );  					// don't change width, as this item is as wide as its parent folder by construction  					itemp->reshape( itemp->getRect().getWidth(), child_height); @@ -1293,7 +957,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  	// animate current height towards target height  	if (llabs(mCurHeight - mTargetHeight) > 1.f)  	{ -		mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); +		mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT));  		requestArrange(); @@ -1342,249 +1006,21 @@ BOOL LLFolderViewFolder::needsArrange()  	return mLastArrangeGeneration < getRoot()->getArrangeGeneration();   } -void LLFolderViewFolder::requestSort() -{ -	mNeedsSort = true; -	// whenever item order changes, we need to lay things out again -	requestArrange(); -} - -void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) -{ -	//mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation); -	mCompletedFilterGeneration = generation; -	// only aggregate up if we are a lower (older) value -	if (recurse_up -		&& mParentFolder -		&& generation < mParentFolder->getCompletedFilterGeneration()) -	{ -		mParentFolder->setCompletedFilterGeneration(generation, TRUE); -	} -} +//TODO RN: get height resetting working +//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) +//{ +//	// if this folder is now filtered, but wasn't before +//	// (it just passed) +//	if (passed && !passedFilter(filter_generation)) +//	{ +//		// reset current height, because last time we drew it +//		// it might have had more visible items than now +//		mCurHeight = 0.f; +//	} +// +//	LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); +//} -void LLFolderViewFolder::filter( LLInventoryFilter& filter) -{ -	S32 filter_generation = filter.getCurrentGeneration(); -	// if failed to pass filter newer than must_pass_generation -	// you will automatically fail this time, so we only -	// check against items that have passed the filter -	S32 must_pass_generation = filter.getMustPassGeneration(); -	 -	bool autoopen_folders = (filter.hasFilterString()); - -	// if we have already been filtered against this generation, skip out -	if (getCompletedFilterGeneration() >= filter_generation) -	{ -		return; -	} - -	// filter folder itself -	if (getLastFilterGeneration() < filter_generation) -	{ -		if (getLastFilterGeneration() >= must_pass_generation	// folder has been compared to a valid precursor filter -			&& !mPassedFilter)									// and did not pass the filter -		{ -			// go ahead and flag this folder as done -			mLastFilterGeneration = filter_generation; -			mStringMatchOffset = std::string::npos; -		} -		else // filter self only on first pass through -		{ -			// filter against folder rules -			filterFolder(filter); -			// and then item rules -			LLFolderViewItem::filter( filter ); -		} -	} - -	if (getRoot()->getDebugFilters()) -	{ -		mStatusText = llformat("%d", mLastFilterGeneration); -		mStatusText += llformat("(%d)", mCompletedFilterGeneration); -		mStatusText += llformat("+%d", mMostFilteredDescendantGeneration); -	} - -	// all descendants have been filtered later than must pass generation -	// but none passed -	if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation)) -	{ -		// don't traverse children if we've already filtered them since must_pass_generation -		// and came back with nothing -		return; -	} - -	// we entered here with at least one filter iteration left -	// check to see if we have any more before continuing on to children -	if (filter.getFilterCount() < 0) -	{ -		return; -	} - -	// when applying a filter, matching folders get their contents downloaded first -	if (filter.isNotDefault() -		&& getFiltered(filter.getMinRequiredGeneration()) -		&&	(mListener -			&& !gInventory.isCategoryComplete(mListener->getUUID()))) -	{ -		LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID()); -	} - -	// now query children -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end(); -		 ++iter) -	{ -		LLFolderViewFolder* folder = (*iter); -		// have we run out of iterations this frame? -		if (filter.getFilterCount() < 0) -		{ -			break; -		} - -		// mMostFilteredDescendantGeneration might have been reset -		// in which case we need to update it even for folders that -		// don't need to be filtered anymore -		if (folder->getCompletedFilterGeneration() >= filter_generation) -		{ -			// track latest generation to pass any child items -			if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration())) -			{ -				mMostFilteredDescendantGeneration = filter_generation; -				requestArrange(); -			} -			// just skip it, it has already been filtered -			continue; -		} - -		// update this folders filter status (and children) -		folder->filter( filter ); - -		// track latest generation to pass any child items -		if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation)) -		{ -			mMostFilteredDescendantGeneration = filter_generation; -			requestArrange(); -			if (getRoot()->needsAutoSelect() && autoopen_folders) -			{ -				folder->setOpenArrangeRecursively(TRUE); -			} -		} -	} - -	for (items_t::iterator iter = mItems.begin(); -		 iter != mItems.end(); -		 ++iter) -	{ -		LLFolderViewItem* item = (*iter); -		if (filter.getFilterCount() < 0) -		{ -			break; -		} -		if (item->getLastFilterGeneration() >= filter_generation) -		{ -			if (item->getFiltered()) -			{ -				mMostFilteredDescendantGeneration = filter_generation; -				requestArrange(); -			} -			continue; -		} - -		if (item->getLastFilterGeneration() >= must_pass_generation &&  -			!item->getFiltered(must_pass_generation)) -		{ -			// failed to pass an earlier filter that was a subset of the current one -			// go ahead and flag this item as done -			item->setFiltered(FALSE, filter_generation); -			continue; -		} - -		item->filter( filter ); - -		if (item->getFiltered(filter.getMinRequiredGeneration())) -		{ -			mMostFilteredDescendantGeneration = filter_generation; -			requestArrange(); -		} -	} - -	// if we didn't use all filter iterations -	// that means we filtered all of our descendants -	// instead of exhausting the filter count for this frame -	if (filter.getFilterCount() > 0) -	{ -		// flag this folder as having completed filter pass for all descendants -		setCompletedFilterGeneration(filter_generation, FALSE/*dont recurse up to root*/); -	} -} - -void LLFolderViewFolder::filterFolder(LLInventoryFilter& filter) -{ -	const BOOL previous_passed_filter = mPassedFolderFilter; -	const BOOL passed_filter = filter.checkFolder(this); - -	// If our visibility will change as a result of this filter, then -	// we need to be rearranged in our parent folder -	if (mParentFolder) -	{ -		if (getVisible() != passed_filter -			|| previous_passed_filter != passed_filter ) -		{ -			mParentFolder->requestArrange(); -		} -	} - -	setFilteredFolder(passed_filter, filter.getCurrentGeneration()); -	filter.decrementFilterCount(); - -	if (getRoot()->getDebugFilters()) -	{ -		mStatusText = llformat("%d", mLastFilterGeneration); -	} -} - -void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation) -{ -	// if this folder is now filtered, but wasn't before -	// (it just passed) -	if (filtered && !mPassedFilter) -	{ -		// reset current height, because last time we drew it -		// it might have had more visible items than now -		mCurHeight = 0.f; -	} - -	LLFolderViewItem::setFiltered(filtered, filter_generation); -} - -void LLFolderViewFolder::dirtyFilter() -{ -	// we're a folder, so invalidate our completed generation -	setCompletedFilterGeneration(-1, FALSE); -	LLFolderViewItem::dirtyFilter(); -} - -BOOL LLFolderViewFolder::getFiltered()  -{  -	return getFilteredFolder(getRoot()->getFilter()->getMinRequiredGeneration())  -		&& LLFolderViewItem::getFiltered();  -} - -BOOL LLFolderViewFolder::getFiltered(S32 filter_generation)  -{ -	return getFilteredFolder(filter_generation) && LLFolderViewItem::getFiltered(filter_generation); -} - -BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation) -{  -	return mMostFilteredDescendantGeneration >= filter_generation;  -} - - -BOOL LLFolderViewFolder::hasFilteredDescendants() -{ -	return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration(); -}  // Passes selection information on to children and record selection  // information if necessary. @@ -1938,14 +1374,6 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection)  void LLFolderViewFolder::destroyView()  { -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		LLFolderViewItem* item = (*iit); -		getRoot()->removeItemID(item->getListener()->getUUID()); -	} -  	std::for_each(mItems.begin(), mItems.end(), DeletePointer());  	mItems.clear(); @@ -1955,42 +1383,8 @@ void LLFolderViewFolder::destroyView()  		folderp->destroyView(); // removes entry from mFolders  	} -	//deleteAllChildren(); - -	if (mParentFolder) -	{ -		mParentFolder->removeView(this); -	} -} - -// remove the specified item (and any children) if possible. Return -// TRUE if the item was deleted. -BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) -{ -	if(item->remove()) -	{ -		return TRUE; +	LLFolderViewItem::destroyView();  	} -	return FALSE; -} - -// simply remove the view (and any children) Don't bother telling the -// listeners. -void LLFolderViewFolder::removeView(LLFolderViewItem* item) -{ -	if (!item || item->getParentFolder() != this) -	{ -		return; -	} -	// deselect without traversing hierarchy -	if (item->isSelected()) -	{ -		item->deselectItem(); -	} -	getRoot()->removeFromSelectionList(item); -	extractItem(item); -	delete item; -}  // extractItem() removes the specified item from the folder, but  // doesn't delete it. @@ -2015,107 +1409,16 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item )  		mItems.erase(it);  	}  	//item has been removed, need to update filter -	dirtyFilter(); +	getViewModelItem()->removeChild(item->getViewModelItem());  	//because an item is going away regardless of filter status, force rearrange  	requestArrange(); -	getRoot()->removeItemID(item->getListener()->getUUID());  	removeChild(item);  } -bool LLFolderViewFolder::isTrash() const -{ -	if (mAmTrash == LLFolderViewFolder::UNKNOWN) -	{ -		mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH; -	} -	return mAmTrash == LLFolderViewFolder::TRASH; -} - -void LLFolderViewFolder::sortBy(U32 order) -{ -	if (!mSortFunction.updateSort(order)) -	{ -		// No changes. -		return; -	} - -	// Propagate this change to sub folders -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		(*fit)->sortBy(order); -	} - -	// Don't sort the topmost folders (My Inventory and Library) -	if (mListener->getUUID().notNull()) -	{ -		mFolders.sort(mSortFunction); -		mItems.sort(mSortFunction); -	} - -	if (order & LLInventoryFilter::SO_DATE) -	{ -		time_t latest = 0; - -		if (!mItems.empty()) -		{ -			LLFolderViewItem* item = *(mItems.begin()); -			latest = item->getCreationDate(); -		} - -		if (!mFolders.empty()) -		{ -			LLFolderViewFolder* folder = *(mFolders.begin()); -			if (folder->getCreationDate() > latest) -			{ -				latest = folder->getCreationDate(); -			} -		} -		mSubtreeCreationDate = latest; -	} -} - -void LLFolderViewFolder::setItemSortOrder(U32 ordering) -{ -	if (mSortFunction.updateSort(ordering)) -	{ -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end();) -		{ -			folders_t::iterator fit = iter++; -			(*fit)->setItemSortOrder(ordering); -		} - -		mFolders.sort(mSortFunction); -		mItems.sort(mSortFunction); -	} -} - -EInventorySortGroup LLFolderViewFolder::getSortGroup() const -{ -	if (isTrash()) -	{ -		return SG_TRASH_FOLDER; -	} - -	if( mListener ) -	{ -		if(LLFolderType::lookupIsProtectedType(mListener->getPreferredType())) -		{ -			return SG_SYSTEM_FOLDER; -		} -	} - -	return SG_NORMAL_FOLDER; -} -  BOOL LLFolderViewFolder::isMovable()  { -	if( mListener ) +	if( !(getViewModelItem()->isItemMovable()) )  	{ -		if( !(mListener->isItemMovable()) ) -		{  			return FALSE;  		} @@ -2138,17 +1441,14 @@ BOOL LLFolderViewFolder::isMovable()  				return FALSE;  			}  		} -	}  	return TRUE;  }  BOOL LLFolderViewFolder::isRemovable()  { -	if( mListener ) +	if( !(getViewModelItem()->isItemRemovable()) )  	{ -		if( !(mListener->isItemRemovable()) ) -		{  			return FALSE;  		} @@ -2171,93 +1471,77 @@ BOOL LLFolderViewFolder::isRemovable()  				return FALSE;  			}  		} -	}  	return TRUE;  }  // this is an internal method used for adding items to folders.  -BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) +void LLFolderViewFolder::addItem(LLFolderViewItem* item) +{ +	if (item->getParentFolder())  { +		item->getParentFolder()->extractItem(item); +	} +	item->setParentFolder(this); +  	mItems.push_back(item);  	item->setRect(LLRect(0, 0, getRect().getWidth(), 0));  	item->setVisible(FALSE);  	addChild(item); +	getViewModelItem()->addChild(item->getViewModelItem()); -	item->dirtyFilter(); +	//TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria +	//// Traverse parent folders and update creation date and resort, if necessary +	//LLFolderViewFolder* parentp = this; +	//while (parentp) +	//{ +	//	if (parentp->mSortFunction.isByDate()) +	//	{ +	//		// parent folder doesn't have a time stamp yet, so get it from us +	//		parentp->requestSort(); +	//	} -	// Update the folder creation date if the child is newer than our current date -	setCreationDate(llmax<time_t>(mCreationDate, item->getCreationDate())); - -	// Handle sorting -	requestArrange(); -	requestSort(); +	//	parentp = parentp->getParentFolder(); +	//} +} -	// Traverse parent folders and update creation date and resort, if necessary -	LLFolderViewFolder* parentp = getParentFolder(); -	while (parentp) +// this is an internal method used for adding items to folders.  +void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)  	{ -		// Update the folder creation date if the child is newer than our current date -		parentp->setCreationDate(llmax<time_t>(parentp->mCreationDate, item->getCreationDate())); - -		if (parentp->mSortFunction.isByDate()) +	if (folder->mParentFolder)  		{ -			// parent folder doesn't have a time stamp yet, so get it from us -			parentp->requestSort(); +		folder->mParentFolder->extractItem(folder);  		} - -		parentp = parentp->getParentFolder(); -	} - -	return TRUE; -} - -// this is an internal method used for adding items to folders.  -BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) -{ +	folder->mParentFolder = this;  	mFolders.push_back(folder);  	folder->setOrigin(0, 0);  	folder->reshape(getRect().getWidth(), 0);  	folder->setVisible(FALSE); -	addChild( folder ); -	folder->dirtyFilter();  	// rearrange all descendants too, as our indentation level might have changed -	folder->requestArrange(TRUE); -	requestSort(); -	LLFolderViewFolder* parentp = getParentFolder(); -	while (parentp && !parentp->mSortFunction.isByDate()) -	{ -		// parent folder doesn't have a time stamp yet, so get it from us -		parentp->requestSort(); -		parentp = parentp->getParentFolder(); +	//folder->requestArrange(); +	//requestSort(); + +	addChild( folder ); +	getViewModelItem()->addChild(folder->getViewModelItem());  	} -	return TRUE; -} -void LLFolderViewFolder::requestArrange(BOOL include_descendants)	 +void LLFolderViewFolder::requestArrange()  {  +	//if ( mLastArrangeGeneration != -1) +	{  	mLastArrangeGeneration = -1;   	// flag all items up to root  	if (mParentFolder)  	{  		mParentFolder->requestArrange();  	} - -	if (include_descendants) -	{ -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end(); -			++iter) -		{ -			(*iter)->requestArrange(TRUE);  		}  	} -}  void LLFolderViewFolder::toggleOpen()  { -	setOpen(!mIsOpen); +	setOpen(!isOpen());  }  // Force a folder open or closed @@ -2268,18 +1552,15 @@ void LLFolderViewFolder::setOpen(BOOL openitem)  void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse)  { -	BOOL was_open = mIsOpen; +	BOOL was_open = isOpen();  	mIsOpen = openitem; -	if (mListener) -	{  		if(!was_open && openitem)  		{ -			mListener->openItem(); +		getViewModelItem()->openItem();  		}  		else if(was_open && !openitem)  		{ -			mListener->closeItem(); -		} +		getViewModelItem()->closeItem();  	}  	if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) @@ -2298,7 +1579,7 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r  		mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP);  	} -	if (was_open != mIsOpen) +	if (was_open != isOpen())  	{  		requestArrange();  	} @@ -2311,7 +1592,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask,  													EAcceptance* accept,  													std::string& tooltip_msg)  { -	BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); +	BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg);  	if (accepted)   	{  		mDragAndDropTarget = TRUE; @@ -2367,23 +1648,6 @@ void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor)  	}  } -void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ -	functor(mListener); -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		(*fit)->applyListenerFunctorRecursively(functor); -	} -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		(*iit)->applyListenerFunctorRecursively(functor); -	} -} -  // LLView functionality  BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,  										   BOOL drop, @@ -2394,7 +1658,7 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,  {  	BOOL handled = FALSE; -	if (mIsOpen) +	if (isOpen())  	{  		handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL);  	} @@ -2416,7 +1680,7 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask,  													   EAcceptance* accept,  													   std::string& tooltip_msg)  { -	BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); +	BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg);  	if (accepted)   	{ @@ -2440,11 +1704,8 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask,  BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask )  {  	BOOL handled = FALSE; -	// fetch contents of this folder, as context menu can depend on contents -	// still, user would have to open context menu again to see the changes -	gInventory.fetchDescendentsOf(mListener->getUUID()); -	if( mIsOpen ) +	if( isOpen() )  	{  		handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;  	} @@ -2474,7 +1735,7 @@ BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask)  BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )  {  	BOOL handled = FALSE; -	if( mIsOpen ) +	if( isOpen() )  	{  		handled = childrenHandleMouseDown(x,y,mask) != NULL;  	} @@ -2497,18 +1758,8 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )  BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )  { -	/* Disable outfit double click to wear -	const LLUUID &cat_uuid = getListener()->getUUID(); -	const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); -	if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) -	{ -		getListener()->performAction(NULL, NULL,"replaceoutfit"); -		return TRUE; -	} -	*/ -  	BOOL handled = FALSE; -	if( mIsOpen ) +	if( isOpen() )  	{  		handled = childrenHandleDoubleClick( x, y, mask ) != NULL;  	} @@ -2522,7 +1773,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )  		}  		else  		{ -			setSelectionFromRoot(this, FALSE); +			getRoot()->setSelection(this, FALSE);  			toggleOpen();  		}  		handled = TRUE; @@ -2536,7 +1787,7 @@ void LLFolderViewFolder::draw()  	{  		mControlLabelRotation = mAutoOpenCountdown * -90.f;  	} -	else if (mIsOpen) +	else if (isOpen())  	{  		mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f));  	} @@ -2545,31 +1796,10 @@ void LLFolderViewFolder::draw()  		mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f));  	} -	bool possibly_has_children = false; -	bool up_to_date = mListener && mListener->isUpToDate(); -	if(!up_to_date -		&& mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) -	{ -		possibly_has_children = true; -	} - - -	BOOL loading = (mIsOpen -					&& possibly_has_children -					&& !up_to_date ); - -	if ( loading && !mIsLoading ) -	{ -		// Measure how long we've been in the loading state -		mTimeSinceRequestStart.reset(); -	} - -	mIsLoading = loading; -  	LLFolderViewItem::draw();  	// draw children if root folder, or any other folder that is open or animating to closed state -	if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight )) +	if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight ))  	{  		LLView::draw();  	} @@ -2577,22 +1807,6 @@ void LLFolderViewFolder::draw()  	mExpanderHighlighted = FALSE;  } -time_t LLFolderViewFolder::getCreationDate() const -{ -	return llmax<time_t>(mCreationDate, mSubtreeCreationDate); -} - - -BOOL	LLFolderViewFolder::potentiallyVisible() -{ -	// folder should be visible by it's own filter status -	return LLFolderViewItem::potentiallyVisible() 	 -		// or one or more of its descendants have passed the minimum filter requirement -		|| hasFilteredDescendants(getRoot()->getFilter()->getMinRequiredGeneration()) -		// or not all of its descendants have been checked against minimum filter requirement -		|| getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration();  -} -  // this does prefix traversal, as folders are listed above their contents  LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children )  { @@ -2804,98 +2018,3 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it  	return result;  } - -bool LLInventorySort::updateSort(U32 order) -{ -	if (order != mSortOrder) -	{ -		mSortOrder = order; -		mByDate = (order & LLInventoryFilter::SO_DATE); -		mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); -		mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); -		return true; -	} -	return false; -} - -bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b) -{ -	// ignore sort order for landmarks in the Favorites folder. -	// they should be always sorted as in Favorites bar. See EXT-719 -	if (a->getSortGroup() == SG_ITEM -		&& b->getSortGroup() == SG_ITEM -		&& a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK -		&& b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) -	{ - -		static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - -		LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID(); -		LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID(); - -		if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) -		{ -			// *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem -			// or to LLInvFVBridge -			LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a->getListener()))->getItem(); -			LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b->getListener()))->getItem(); -			if (!aitem || !bitem) -				return false; -			S32 a_sort = aitem->getSortField(); -			S32 b_sort = bitem->getSortField(); -			return a_sort < b_sort; -		} -	} - -	// We sort by name if we aren't sorting by date -	// OR if these are folders and we are sorting folders by name. -	bool by_name = (!mByDate  -		|| (mFoldersByName  -		&& (a->getSortGroup() != SG_ITEM))); - -	if (a->getSortGroup() != b->getSortGroup()) -	{ -		if (mSystemToTop) -		{ -			// Group order is System Folders, Trash, Normal Folders, Items -			return (a->getSortGroup() < b->getSortGroup()); -		} -		else if (mByDate) -		{ -			// Trash needs to go to the bottom if we are sorting by date -			if ( (a->getSortGroup() == SG_TRASH_FOLDER) -				|| (b->getSortGroup() == SG_TRASH_FOLDER)) -			{ -				return (b->getSortGroup() == SG_TRASH_FOLDER); -			} -		} -	} - -	if (by_name) -	{ -		S32 compare = LLStringUtil::compareDict(a->getLabel(), b->getLabel()); -		if (0 == compare) -		{ -			return (a->getCreationDate() > b->getCreationDate()); -		} -		else -		{ -			return (compare < 0); -		} -	} -	else -	{ -		// BUG: This is very very slow.  The getCreationDate() is log n in number -		// of inventory items. -		time_t first_create = a->getCreationDate(); -		time_t second_create = b->getCreationDate(); -		if (first_create == second_create) -		{ -			return (LLStringUtil::compareDict(a->getLabel(), b->getLabel()) < 0); -		} -		else -		{ -			return (first_create > second_create); -		} -	} -} diff --git a/indra/newview/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 577b6b54a2..6eacbe8bd0 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -27,54 +27,14 @@  #define LLFOLDERVIEWITEM_H  #include "llview.h" -#include "lldarray.h"  // *TODO: Eliminate, forward declare  #include "lluiimage.h" -class LLFontGL;  class LLFolderView; -class LLFolderViewEventListener; +class LLFolderViewModelItem;  class LLFolderViewFolder;  class LLFolderViewFunctor; -class LLFolderViewItem; -class LLFolderViewListenerFunctor; -class LLInventoryFilter; -class LLMenuGL; -class LLUIImage; -class LLViewerInventoryItem; - -// These are grouping of inventory types. -// Order matters when sorting system folders to the top. -enum EInventorySortGroup -{  -	SG_SYSTEM_FOLDER,  -	SG_TRASH_FOLDER,  -	SG_NORMAL_FOLDER,  -	SG_ITEM  -}; - -// *TODO: do we really need one sort object per folder? -// can we just have one of these per LLFolderView ? -class LLInventorySort -{ -public: -	LLInventorySort()  -		: mSortOrder(0), -		mByDate(false), -		mSystemToTop(false), -		mFoldersByName(false) { } - -	// Returns true if order has changed -	bool updateSort(U32 order); -	U32 getSort() { return mSortOrder; } -	bool isByDate() { return mByDate; } - -	bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b); -private: -	U32  mSortOrder; -	bool mByDate; -	bool mSystemToTop; -	bool mFoldersByName; -}; +class LLFolderViewFilter; +class LLFolderViewModelInterface;  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLFolderViewItem @@ -86,135 +46,96 @@ private:  class LLFolderViewItem : public LLView  {  public: -	static void initClass(); -	static void cleanupClass(); -  	struct Params : public LLInitParam::Block<Params, LLView::Params>  	{ -		Optional<LLUIImage*>					icon; -		Optional<LLUIImage*>					icon_open;  // used for folders -		Optional<LLUIImage*>					icon_overlay;  // for links -		Optional<LLFolderView*>					root; -		Mandatory<LLFolderViewEventListener*>	listener; +		Optional<LLUIImage*>						folder_arrow_image, +													selection_image; +		Mandatory<LLFolderView*>					root; +		Mandatory<LLFolderViewModelItem*>			listener; -		Optional<LLUIImage*>					folder_arrow_image; -		Optional<S32>							folder_indentation; // pixels -		Optional<LLUIImage*>					selection_image; -		Optional<S32>							item_height; // pixels -		Optional<S32>							item_top_pad; // pixels +		Optional<S32>								folder_indentation, // pixels +													item_height, +													item_top_pad; -		Optional<S32>							creation_date; //UTC seconds +		Optional<time_t>							creation_date; +		Optional<bool>								allow_open;  		Params();  	};  	// layout constants -	static const S32 LEFT_PAD = 5; -	// LEFT_INDENTATION is set via folder_indentation above -	static const S32 ICON_PAD = 2; -	static const S32 ICON_WIDTH = 16; -	static const S32 TEXT_PAD = 1; -	static const S32 TEXT_PAD_RIGHT = 4; -	static const S32 ARROW_SIZE = 12; -	static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; -	// animation parameters -	static const F32 FOLDER_CLOSE_TIME_CONSTANT; -	static const F32 FOLDER_OPEN_TIME_CONSTANT; - -	// Mostly for debugging printout purposes. -	const std::string& getSearchableLabel() { return mSearchableLabel; } +	static const S32	LEFT_PAD = 5, +						ICON_PAD = 2, +						ICON_WIDTH = 16, +						TEXT_PAD = 1, +						TEXT_PAD_RIGHT = 4, +						ARROW_SIZE = 12, +						MAX_FOLDER_ITEM_OVERLAP = 2; -	BOOL isLoading() const { return mIsLoading; } - -private: -	BOOL						mIsSelected; +	// animation parameters +	static const F32	FOLDER_CLOSE_TIME_CONSTANT, +						FOLDER_OPEN_TIME_CONSTANT;  protected:  	friend class LLUICtrlFactory; -	friend class LLFolderViewEventListener; +	friend class LLFolderViewModelItem;  	LLFolderViewItem(const Params& p);  	std::string					mLabel; -	std::string					mSearchableLabel;  	S32							mLabelWidth;  	bool						mLabelWidthDirty; -	time_t						mCreationDate;  	LLFolderViewFolder*			mParentFolder; -	LLFolderViewEventListener*	mListener; -	BOOL						mIsCurSelection; -	BOOL						mSelectPending; +	LLFolderViewModelItem*		mViewModelItem;  	LLFontGL::StyleFlags		mLabelStyle;  	std::string					mLabelSuffix; -	LLUIImagePtr				mIcon; -	std::string					mStatusText; -	LLUIImagePtr				mIconOpen; -	LLUIImagePtr				mIconOverlay; -	BOOL						mHasVisibleChildren; +	LLUIImagePtr				mIcon, +								mIconOpen, +								mIconOverlay;  	S32							mIndentation;  	S32							mItemHeight; -	BOOL						mPassedFilter; -	S32							mLastFilterGeneration; -	std::string::size_type		mStringMatchOffset; +	S32							mDragStartX, +								mDragStartY; +  	F32							mControlLabelRotation;  	LLFolderView*				mRoot; -	BOOL						mDragAndDropTarget; -	BOOL                        mIsLoading; -	LLTimer                     mTimeSinceRequestStart; -	bool						mShowLoadStatus; -	bool						mIsMouseOverTitle; - -	// helper function to change the selection from the root. -	void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); +	bool						mHasVisibleChildren, +								mIsCurSelection, +								mDragAndDropTarget, +								mIsMouseOverTitle, +								mAllowOpen, +								mSelectPending;  	// this is an internal method used for adding items to folders. A  	// no-op at this level, but reimplemented in derived classes. -	virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } -	virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } +	virtual void addItem(LLFolderViewItem*) { } +	virtual void addFolder(LLFolderViewFolder*) { }  	static LLFontGL* getLabelFontForStyle(U8 style); -	virtual void setCreationDate(time_t creation_date_utc)	{ mCreationDate = creation_date_utc; } +private: +	BOOL						mIsSelected;  public: +	static void initClass(); +	static void cleanupClass(); +  	BOOL postBuild(); -	// This function clears the currently selected item, and records -	// the specified selected item appropriately for display and use -	// in the UI. If open is TRUE, then folders are opened up along -	// the way to the selection. -	void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem, -		BOOL take_keyboard_focus = TRUE); - -	// This function is called when the folder view is dirty. It's -	// implemented here but called by derived classes when folding the -	// views. -	void arrangeFromRoot(); -	void filterFromRoot( void ); -	 +	virtual void openItem( void ); +  	void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus);  	virtual ~LLFolderViewItem( void );  	// addToFolder() returns TRUE if it succeeds. FALSE otherwise -	enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; -	virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); - -	virtual EInventorySortGroup getSortGroup() const; +	virtual void addToFolder(LLFolderViewFolder* folder);  	// Finds width and height of this object and it's children.  Also  	// 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 arrange( S32* width, S32* height );  	virtual S32 getItemHeight(); -	// applies filters to control visibility of inventory items -	virtual void filter( LLInventoryFilter& filter); - -	// updates filter serial number and optionally propagated value up to root -	S32		getLastFilterGeneration() { return mLastFilterGeneration; } - -	virtual void	dirtyFilter(); -  	// If 'selection' is 'this' then note that otherwise ignore.  	// Returns TRUE if this item ends up being selected.  	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); @@ -231,7 +152,7 @@ public:  	virtual void selectItem();  	// gets multiple-element selection -	virtual std::set<LLUUID> getSelectionList() const; +	virtual std::set<LLFolderViewItem*> getSelectionList() const;  	// Returns true is this object and all of its children can be removed (deleted by user)  	virtual BOOL isRemovable(); @@ -253,74 +174,54 @@ public:  	BOOL hasVisibleChildren() { return mHasVisibleChildren; } -	void setShowLoadStatus(bool status) { mShowLoadStatus = status; } -  	// Call through to the viewed object and return true if it can be  	// removed. Returns true if it's removed.  	//virtual BOOL removeRecursively(BOOL single_item);  	BOOL remove();  	// Build an appropriate context menu for the item.	Flags unused. -	void buildContextMenu(LLMenuGL& menu, U32 flags); +	void buildContextMenu(class LLMenuGL& menu, U32 flags);  	// This method returns the actual name of the thing being  	// viewed. This method will ask the viewed object itself.  	const std::string& getName( void ) const; -	const std::string& getSearchableLabel( void ) const; -  	// This method returns the label displayed on the view. This  	// method was primarily added to allow sorting on the folder  	// contents possible before the entire view has been constructed.  	const std::string& getLabel() const { return mLabel; } -	// Used for sorting, like getLabel() above. -	virtual time_t getCreationDate() const { return mCreationDate; } -  	LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; }  	const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } +	void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } +  	LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE );  	LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); -	const LLFolderViewEventListener* getListener( void ) const { return mListener; } -	LLFolderViewEventListener* getListener( void ) { return mListener; } -	 -	// Gets the inventory item if it exists (null otherwise) -	LLViewerInventoryItem * getInventoryItem(void); +	const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } +	LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } + +	const LLFolderViewModelInterface* getFolderViewModel( void ) const; +	LLFolderViewModelInterface* getFolderViewModel( void );  	// just rename the object.  	void rename(const std::string& new_name); -	// open -	virtual void openItem( void ); -	virtual void preview(void); - -	// Show children (unfortunate that this is called "open") +	// Show children  	virtual void setOpen(BOOL open = TRUE) {}; -  	virtual BOOL isOpen() const { return FALSE; }  	virtual LLFolderView*	getRoot(); +	virtual const LLFolderView*	getRoot() const;  	BOOL			isDescendantOf( const LLFolderViewFolder* potential_ancestor );  	S32				getIndentation() { return mIndentation; } -	virtual BOOL	potentiallyVisible(); // do we know for a fact that this item won't be displayed? -	virtual BOOL	potentiallyFiltered(); // do we know for a fact that this item has been filtered out? - -	virtual BOOL	getFiltered(); -	virtual BOOL	getFiltered(S32 filter_generation); -	virtual void	setFiltered(BOOL filtered, S32 filter_generation); - -	// change the icon -	void setIcon(LLUIImagePtr icon); +	virtual BOOL	passedFilter(S32 filter_generation = -1);  	// refresh information from the object being viewed. -	void refreshFromListener();  	virtual void refresh(); -	virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); -  	// LLView functionality  	virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );  	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); @@ -335,20 +236,15 @@ public:  	//	virtual void handleDropped();  	virtual void draw();  	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -		EDragAndDropType cargo_type, -		void* cargo_data, -		EAcceptance* accept, -		std::string& tooltip_msg); +									EDragAndDropType cargo_type, +									void* cargo_data, +									EAcceptance* accept, +									std::string& tooltip_msg);  private:  	static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts  }; - -// function used for sorting. -typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b); - -  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLFolderViewFolder  // @@ -364,32 +260,22 @@ protected:  	friend class LLUICtrlFactory;  public: -	typedef enum e_trash -	{ -		UNKNOWN, TRASH, NOT_TRASH -	} ETrash; -  	typedef std::list<LLFolderViewItem*> items_t;  	typedef std::list<LLFolderViewFolder*> folders_t;  protected:  	items_t mItems;  	folders_t mFolders; -	LLInventorySort	mSortFunction;  	BOOL		mIsOpen;  	BOOL		mExpanderHighlighted;  	F32			mCurHeight;  	F32			mTargetHeight;  	F32			mAutoOpenCountdown; -	time_t		mSubtreeCreationDate; -	mutable ETrash mAmTrash;  	S32			mLastArrangeGeneration;  	S32			mLastCalculatedWidth; -	S32			mCompletedFilterGeneration;  	S32			mMostFilteredDescendantGeneration;  	bool		mNeedsSort; -	bool		mPassedFolderFilter;  public:  	typedef enum e_recurse_type @@ -403,48 +289,25 @@ public:  	virtual ~LLFolderViewFolder( void ); -	virtual BOOL	potentiallyVisible(); -  	LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE );  	LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE  );  	// addToFolder() returns TRUE if it succeeds. FALSE otherwise -	virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); +	virtual void addToFolder(LLFolderViewFolder* folder);  	// Finds width and height of this object and it's children.  Also  	// 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 arrange( S32* width, S32* height );  	BOOL needsArrange(); -	void requestSort(); - -	// Returns the sort group (system, trash, folder) for this folder. -	virtual EInventorySortGroup getSortGroup() const; - -	virtual void	setCompletedFilterGeneration(S32 generation, BOOL recurse_up); -	virtual S32		getCompletedFilterGeneration() { return mCompletedFilterGeneration; } -	BOOL hasFilteredDescendants(S32 filter_generation); -	BOOL hasFilteredDescendants(); - -	// applies filters to control visibility of inventory items -	virtual void filter( LLInventoryFilter& filter); -	virtual void setFiltered(BOOL filtered, S32 filter_generation); -	virtual BOOL getFiltered(); -	virtual BOOL getFiltered(S32 filter_generation); - -	virtual void dirtyFilter(); -	 -	// folder-specific filtering (filter status propagates top down instead of bottom up) -	void filterFolder(LLInventoryFilter& filter); -	void setFilteredFolder(bool filtered, S32 filter_generation); -	bool getFilteredFolder(S32 filter_generation); +	bool descendantsPassedFilter(S32 filter_generation = -1);  	// Passes selection information on to children and record  	// selection information if necessary.  	// Returns TRUE if this object (or a child) ends up being selected.  	// If 'openitem' is TRUE then folders are opened up along the way to the selection. -	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); +	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE);  	// This method is used to change the selection of an item.  	// Recursively traverse all children; if 'selection' is 'this' then change @@ -464,31 +327,13 @@ public:  	// destroys this folder, and all children  	virtual void destroyView(); -	// If this folder can be removed, remove all children that can be -	// removed, return TRUE if this is empty after the operation and -	// it's viewed folder object can be removed. -	//virtual BOOL removeRecursively(BOOL single_item); -	//virtual BOOL remove(); - -	// remove the specified item (and any children) if -	// possible. Return TRUE if the item was deleted. -	BOOL removeItem(LLFolderViewItem* item); - -	// simply remove the view (and any children) Don't bother telling -	// the listeners. -	void removeView(LLFolderViewItem* item); -  	// extractItem() removes the specified item from the folder, but  	// doesn't delete it. -	void extractItem( LLFolderViewItem* item ); +	virtual void extractItem( LLFolderViewItem* item );  	// This function is called by a child that needs to be resorted.  	void resort(LLFolderViewItem* item); -	void setItemSortOrder(U32 ordering); -	void sortBy(U32); -	//BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b)); -  	void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; }  	// folders can be opened. This will usually be called by internal @@ -499,8 +344,7 @@ public:  	virtual void setOpen(BOOL openitem = TRUE);  	// Called when a child is refreshed. -	// don't rearrange child folder contents unless explicitly requested -	virtual void requestArrange(BOOL include_descendants = FALSE); +	virtual void requestArrange();  	// internal method which doesn't update the entire view. This  	// method was written because the list iterators destroy the state @@ -513,65 +357,60 @@ public:  	// special case if an object is dropped on the child.  	BOOL handleDragAndDropFromChild(MASK mask, -		BOOL drop, -		EDragAndDropType cargo_type, -		void* cargo_data, -		EAcceptance* accept, -		std::string& tooltip_msg); +									BOOL drop, +									EDragAndDropType cargo_type, +									void* cargo_data, +									EAcceptance* accept, +									std::string& tooltip_msg); -	void applyFunctorRecursively(LLFolderViewFunctor& functor); -	virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor);  	// Just apply this functor to the folder's immediate children.  	void applyFunctorToChildren(LLFolderViewFunctor& functor); +	// apply this functor to the folder's descendants. +	void applyFunctorRecursively(LLFolderViewFunctor& functor);  	virtual void openItem( void ); -	virtual BOOL addItem(LLFolderViewItem* item); -	virtual BOOL addFolder( LLFolderViewFolder* folder);  	// LLView functionality  	virtual BOOL handleHover(S32 x, S32 y, MASK mask);  	virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );  	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );  	virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); -	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -		EDragAndDropType cargo_type, -		void* cargo_data, -		EAcceptance* accept, -		std::string& tooltip_msg); -	BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, +	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,  +									BOOL drop, +									EDragAndDropType cargo_type, +									void* cargo_data, +									EAcceptance* accept, +									std::string& tooltip_msg); +	BOOL handleDragAndDropToThisFolder(MASK mask,  +										BOOL drop,  									   EDragAndDropType cargo_type,  									   void* cargo_data,  									   EAcceptance* accept,  									   std::string& tooltip_msg);  	virtual void draw(); -	time_t getCreationDate() const; -	bool isTrash() const; - -	folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); } -	folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); } +	folders_t::iterator getFoldersBegin() { return mFolders.begin(); } +	folders_t::iterator getFoldersEnd() { return mFolders.end(); }  	folders_t::size_type getFoldersCount() const { return mFolders.size(); }  	items_t::const_iterator getItemsBegin() const { return mItems.begin(); }  	items_t::const_iterator getItemsEnd() const { return mItems.end(); }  	items_t::size_type getItemsCount() const { return mItems.size(); } +  	LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse);  	void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse,  std::vector<LLFolderViewItem*>& items); -}; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewListenerFunctor -// -// This simple abstract base class can be used to applied to all -// listeners in a hierarchy. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +	// internal functions for tracking folders and items separately +	// use addToFolder() virtual method to ensure folders are always added to mFolders +	// and not mItems +	void addItem(LLFolderViewItem* item); +	void addFolder( LLFolderViewFolder* folder); -class LLFolderViewListenerFunctor -{ -public: -	virtual ~LLFolderViewListenerFunctor() {} -	virtual void operator()(LLFolderViewEventListener* listener) = 0; +	//WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead +	template<typename SORT_FUNC> void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } +	template<typename SORT_FUNC> void sortItems(const SORT_FUNC& func) { mItems.sort(func); }  }; +  #endif  // LLFOLDERVIEWITEM_H diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp new file mode 100644 index 0000000000..3593804554 --- /dev/null +++ b/indra/llui/llfolderviewmodel.cpp @@ -0,0 +1,68 @@ +/**  + * @file llfolderviewmodel.cpp + * @brief Implementation of the view model collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfolderviewmodel.h" +#include "lltrans.h" + +bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) +{ +	return item->getSortVersion() < mTargetSortVersion; +} + +std::string LLFolderViewModelCommon::getStatusText() +{ +	if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter().getCurrentGeneration()) +	{ +		return LLTrans::getString("Searching"); +	} +	else +	{ +		return getFilter().getEmptyLookupMessage(); +	} +} + +void LLFolderViewModelCommon::filter() +{ +	getFilter().setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); +	mFolderView->getViewModelItem()->filter(getFilter()); +} + +bool LLFolderViewModelItemCommon::hasFilterStringMatch() +{ +	return mStringMatchOffsetFilter != std::string::npos; +} + +std::string::size_type LLFolderViewModelItemCommon::getFilterStringOffset() +{ +	return mStringMatchOffsetFilter; +} + +std::string::size_type LLFolderViewModelItemCommon::getFilterStringSize() +{ +	return mRootViewModel.getFilter().getFilterStringSize(); +} diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h new file mode 100644 index 0000000000..41660c6e1e --- /dev/null +++ b/indra/llui/llfolderviewmodel.h @@ -0,0 +1,417 @@ +/**  + * @file llfolderviewmodel.h + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ +#ifndef LLFOLDERVIEWMODEL_H +#define LLFOLDERVIEWMODEL_H + +#include "llfontgl.h"	// just for StyleFlags enum +#include "llfolderview.h" + +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ +	SG_SYSTEM_FOLDER, +	SG_TRASH_FOLDER, +	SG_NORMAL_FOLDER, +	SG_ITEM +}; + +class LLFontGL; +class LLInventoryModel; +class LLMenuGL; +class LLUIImage; +class LLUUID; +class LLFolderViewItem; +class LLFolderViewFolder; + +class LLFolderViewFilter +{ +public: +	enum EFilterModified +	{ +		FILTER_NONE,				// nothing to do, already filtered +		FILTER_RESTART,				// restart filtering from scratch +		FILTER_LESS_RESTRICTIVE,	// existing filtered items will certainly pass this filter +		FILTER_MORE_RESTRICTIVE		// if you didn't pass the previous filter, you definitely won't pass this one +	}; + +public: + +	LLFolderViewFilter() {} +	virtual ~LLFolderViewFilter() {} + +	// +-------------------------------------------------------------------+ +	// + Execution And Results +	// +-------------------------------------------------------------------+ +	virtual bool 				check(const LLFolderViewModelItem* item) = 0; +	virtual bool				checkFolder(const LLFolderViewModelItem* folder) const = 0; + +	virtual void 				setEmptyLookupMessage(const std::string& message) = 0; +	virtual std::string			getEmptyLookupMessage() const = 0; + +	virtual bool				showAllResults() const = 0; + +	virtual std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const = 0; +	virtual std::string::size_type getFilterStringSize() const = 0; +	// +-------------------------------------------------------------------+ +	// + Status +	// +-------------------------------------------------------------------+ +	virtual bool 				isActive() const = 0; +	virtual bool 				isModified() const = 0; +	virtual void 				clearModified() = 0; +	virtual const std::string& 	getName() const = 0; +	virtual const std::string& 	getFilterText() = 0; +	//RN: this is public to allow system to externally force a global refilter +	virtual void 				setModified(EFilterModified behavior = FILTER_RESTART) = 0; + +	// +-------------------------------------------------------------------+ +	// + Count +	// +-------------------------------------------------------------------+ +	virtual void 				setFilterCount(S32 count) = 0; +	virtual S32 				getFilterCount() const = 0; +	virtual void 				decrementFilterCount() = 0; + +	// +-------------------------------------------------------------------+ +	// + Default +	// +-------------------------------------------------------------------+ +	virtual bool 				isDefault() const = 0; +	virtual bool 				isNotDefault() const = 0; +	virtual void 				markDefault() = 0; +	virtual void 				resetDefault() = 0; + +	// +-------------------------------------------------------------------+ +	// + Generation +	// +-------------------------------------------------------------------+ +	virtual S32 				getCurrentGeneration() const = 0; +	virtual S32 				getFirstSuccessGeneration() const = 0; +	virtual S32 				getFirstRequiredGeneration() const = 0; +}; + +class LLFolderViewModelInterface +{ +public: +	virtual ~LLFolderViewModelInterface() {} +	virtual void requestSortAll() = 0; + +	virtual void sort(class LLFolderViewFolder*) = 0; +	virtual void filter() = 0; + +	virtual bool contentsReady() = 0; +	virtual void setFolderView(LLFolderView* folder_view) = 0; +	virtual LLFolderViewFilter& getFilter() = 0; +	virtual const LLFolderViewFilter& getFilter() const = 0; +	virtual std::string getStatusText() = 0; + +	virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0; +}; + +// This is am abstract base class that users of the folderview classes +// would use to bridge the folder view with the underlying data +class LLFolderViewModelItem +{ +public: +	virtual ~LLFolderViewModelItem( void ) {}; + +	virtual void update() {}	//called when drawing +	virtual const std::string& getName() const = 0; +	virtual const std::string& getDisplayName() const = 0; +	virtual const std::string& getSearchableName() const = 0; + +	virtual LLPointer<LLUIImage> getIcon() const = 0; +	virtual LLPointer<LLUIImage> getIconOpen() const { return getIcon(); } +	virtual LLPointer<LLUIImage> getIconOverlay() const { return NULL; } + +	virtual LLFontGL::StyleFlags getLabelStyle() const = 0; +	virtual std::string getLabelSuffix() const = 0; + +	virtual void openItem( void ) = 0; +	virtual void closeItem( void ) = 0; +	virtual void selectItem(void) = 0; + +	virtual BOOL isItemRenameable() const = 0; +	virtual BOOL renameItem(const std::string& new_name) = 0; + +	virtual BOOL isItemMovable( void ) const = 0;		// Can be moved to another folder +	virtual void move( LLFolderViewModelItem* parent_listener ) = 0; + +	virtual BOOL isItemRemovable( void ) const = 0;		// Can be destroyed +	virtual BOOL removeItem() = 0; +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; + +	virtual BOOL isItemCopyable() const = 0; +	virtual BOOL copyToClipboard() const = 0; +	virtual BOOL cutToClipboard() const = 0; + +	virtual BOOL isClipboardPasteable() const = 0; +	virtual void pasteFromClipboard() = 0; +	virtual void pasteLinkFromClipboard() = 0; + +	virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; +	 +	virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? + +	virtual bool filter( LLFolderViewFilter& filter) = 0; +	virtual bool passedFilter(S32 filter_generation = -1) = 0; +	virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; +	virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) = 0; +	virtual void setPassedFolderFilter(bool passed, S32 filter_generation) = 0; +	virtual void dirtyFilter() = 0; +	virtual bool hasFilterStringMatch() = 0; +	virtual std::string::size_type getFilterStringOffset() = 0; +	virtual std::string::size_type getFilterStringSize() = 0; + +	virtual S32	getLastFilterGeneration() const = 0; + +	virtual bool hasChildren() const = 0; +	virtual void addChild(LLFolderViewModelItem* child) = 0; +	virtual void removeChild(LLFolderViewModelItem* child) = 0; + +	// This method will be called to determine if a drop can be +	// performed, and will set drop to TRUE if a drop is +	// requested. Returns TRUE if a drop is possible/happened, +	// otherwise FALSE. +	virtual BOOL dragOrDrop(MASK mask, BOOL drop, +							EDragAndDropType cargo_type, +							void* cargo_data, +							std::string& tooltip_msg) = 0; + +	virtual void requestSort() = 0; +	virtual S32 getSortVersion() = 0; +	virtual void setSortVersion(S32 version) = 0; +	virtual void setParent(LLFolderViewModelItem* parent) = 0; + +protected: + +	friend class LLFolderViewItem; +	virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; + +}; + +class LLFolderViewModelItemCommon : public LLFolderViewModelItem +{ +public: +	LLFolderViewModelItemCommon(LLFolderViewModelInterface& root_view_model) +	:	mSortVersion(-1), +		mPassedFilter(true), +		mPassedFolderFilter(true), +		mStringMatchOffsetFilter(std::string::npos), +		mStringFilterSize(0), +		mFolderViewItem(NULL), +		mLastFilterGeneration(-1), +		mLastFolderFilterGeneration(-1), +		mMostFilteredDescendantGeneration(-1), +		mParent(NULL), +		mRootViewModel(root_view_model) +	{ +		std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); +	} + +	void requestSort() { mSortVersion = -1; } +	S32 getSortVersion() { return mSortVersion; } +	void setSortVersion(S32 version) { mSortVersion = version;} + +	S32	getLastFilterGeneration() const { return mLastFilterGeneration; } +	S32	getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; } +	void dirtyFilter() +	{ +		mLastFilterGeneration = -1; +		mLastFolderFilterGeneration = -1; + +		// bubble up dirty flag all the way to root +		if (mParent) +		{ +			mParent->dirtyFilter(); +		}	 +	} +	bool hasFilterStringMatch(); +	std::string::size_type getFilterStringOffset(); +	std::string::size_type getFilterStringSize(); +	 +	virtual void addChild(LLFolderViewModelItem* child)  +	{  +		mChildren.push_back(child);  +		child->setParent(this);  +		dirtyFilter(); +		requestSort(); +	} +	virtual void removeChild(LLFolderViewModelItem* child)  +	{  +		mChildren.remove(child);  +		child->setParent(NULL);  +		dirtyFilter(); +	} + +	void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) +	{ +		mPassedFilter = passed; +		mLastFilterGeneration = filter_generation; +		mStringMatchOffsetFilter = string_offset; +		mStringFilterSize = string_size; +	} + +	void setPassedFolderFilter(bool passed, S32 filter_generation) +	{ +		mPassedFolderFilter = passed; +		mLastFolderFilterGeneration = filter_generation; +	} + +	virtual bool potentiallyVisible() +	{ +		return passedFilter() // we've passed the filter +			|| getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration() // or we don't know yet +			|| descendantsPassedFilter(); +	} + +	virtual bool passedFilter(S32 filter_generation = -1)  +	{  +		if (filter_generation < 0)  +			filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); + +		bool passed_folder_filter = mPassedFolderFilter && mLastFolderFilterGeneration >= filter_generation; +		bool passed_filter = mPassedFilter && mLastFilterGeneration >= filter_generation; +		return passed_folder_filter +				&& (descendantsPassedFilter(filter_generation) +					|| passed_filter); +	} + +	virtual bool descendantsPassedFilter(S32 filter_generation = -1) +	{  +		if (filter_generation < 0) filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); +		return mMostFilteredDescendantGeneration >= filter_generation;  +	} + + +protected: +	virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } + +	S32						mSortVersion; +	bool					mPassedFilter; +	bool					mPassedFolderFilter; +	std::string::size_type	mStringMatchOffsetFilter; +	std::string::size_type	mStringFilterSize; + +	S32						mLastFilterGeneration; +	S32						mLastFolderFilterGeneration; +	S32						mMostFilteredDescendantGeneration; + + +	typedef std::list<LLFolderViewModelItem*> child_list_t; +	child_list_t			mChildren; +	LLFolderViewModelItem*	mParent; +	LLFolderViewModelInterface& mRootViewModel; + +	void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} +	LLFolderViewItem*		mFolderViewItem; +}; + + + +class LLFolderViewModelCommon : public LLFolderViewModelInterface +{ +public: +	LLFolderViewModelCommon() +	:	mTargetSortVersion(0), +		mFolderView(NULL) +	{} + +	virtual void requestSortAll() +	{ +		// sort everything +		mTargetSortVersion++; +	} +	virtual std::string getStatusText(); +	virtual void filter(); + +	void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} + +protected: +	bool needsSort(class LLFolderViewModelItem* item); + +	S32 mTargetSortVersion; +	LLFolderView* mFolderView; + +}; + +template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> +class LLFolderViewModel : public LLFolderViewModelCommon +{ +public: +	LLFolderViewModel(){} +	virtual ~LLFolderViewModel() {} + +	typedef SORT_TYPE		SortType; +	typedef ITEM_TYPE		ItemType; +	typedef FOLDER_TYPE		FolderType; +	typedef FILTER_TYPE		FilterType; + +	virtual SortType& getSorter()					 { return mSorter; } +	virtual const SortType& getSorter() const 		 { return mSorter; } +	virtual void setSorter(const SortType& sorter) 	 { mSorter = sorter; requestSortAll(); } + +	virtual FilterType& getFilter() 				 { return mFilter; } +	virtual const FilterType& getFilter() const		 { return mFilter; } +	virtual void setFilter(const FilterType& filter) { mFilter = filter; } + +	// TODO RN: remove this and put all filtering logic in view model +	// add getStatusText and isFiltering() +	virtual bool contentsReady()					{ return true; } + + +	struct ViewModelCompare +	{ +		ViewModelCompare(const SortType& sorter) +		:	mSorter(sorter) +		{} + +		bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const +		{ +			return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); +		} + +		bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const +		{ +			return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); +		} + +		const SortType& mSorter; +	}; + +	void sort(LLFolderViewFolder* folder) +	{ +		if (needsSort(folder->getViewModelItem())) +		{ +			folder->sortFolders(ViewModelCompare(getSorter())); +			folder->sortItems(ViewModelCompare(getSorter())); +			folder->getViewModelItem()->setSortVersion(mTargetSortVersion); +			folder->requestArrange(); +		} +	} + +protected: +	SortType		mSorter; +	FilterType		mFilter; +}; + +#endif // LLFOLDERVIEWMODEL_H diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h index 37c657dd92..680a1a7f1d 100644 --- a/indra/llui/llhandle.h +++ b/indra/llui/llhandle.h @@ -158,13 +158,6 @@ public:  		return mHandle;   	} -protected: -	typedef LLHandle<T> handle_type_t; -	LLHandleProvider()  -	{ -		// provided here to enforce T deriving from LLHandleProvider<T> -	}  -  	template <typename U>  	LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const  	{ @@ -173,6 +166,12 @@ protected:  		return downcast_handle;  	} +protected: +	typedef LLHandle<T> handle_type_t; +	LLHandleProvider()  +	{ +		// provided here to enforce T deriving from LLHandleProvider<T> +	}   private:  	mutable LLRootHandle<T> mHandle; diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 648cd5fdce..883331c792 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -179,6 +179,8 @@ public:  	F32 getVisibleAmount() const;  	S32 getVisibleDim() const; +	bool isCollapsed() const { return mCollapsed;} +  	void setOrientation(LLLayoutStack::ELayoutOrientation orientation);  	void storeOriginalDim(); diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index 6ac38f5ad4..1ede5b706f 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -52,7 +52,7 @@ LLLoadingIndicator::LLLoadingIndicator(const Params& p)  void LLLoadingIndicator::initFromParams(const Params& p)  { -	BOOST_FOREACH(LLUIImage* image, p.images.image) +	BOOST_FOREACH(LLUIImage* image, p.images().image)  	{  		mImages.push_back(image);  	} diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h index c1f979c111..ffcb329f42 100644 --- a/indra/llui/llloadingindicator.h +++ b/indra/llui/llloadingindicator.h @@ -51,7 +51,7 @@ class LLLoadingIndicator  	LOG_CLASS(LLLoadingIndicator);  public: -	struct Images : public LLInitParam::BatchBlock<Images> +	struct Images : public LLInitParam::Block<Images>  	{  		Multiple<LLUIImage*>	image; @@ -62,8 +62,8 @@ public:  	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>  	{ -		Optional<F32>			images_per_sec; -		Optional<Images>		images; +		Optional<F32>				images_per_sec; +		Optional<Atomic<Images> >	images;  		Params()  		:	images_per_sec("images_per_sec", 1.0f), diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 50d59f79f4..746ade4648 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -44,33 +44,27 @@ void LLMenuButton::MenuPositions::declareValues()  LLMenuButton::Params::Params()  :	menu_filename("menu_filename"), -	position("position", MP_BOTTOM_LEFT) +	position("menu_position", MP_BOTTOM_LEFT)  { +	addSynonym(position, "position");  }  LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)  :	LLButton(p),  	mIsMenuShown(false), -	mMenuPosition(p.position) +	mMenuPosition(p.position), +	mOwnMenu(false)  {  	std::string menu_filename = p.menu_filename; -	if (!menu_filename.empty()) -	{ -		LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); -		if (!menu) -		{ -			llwarns << "Error loading menu_button menu" << llendl; -			return; -		} - -		menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); - -		mMenuHandle = menu->getHandle(); +	setMenu(menu_filename, mMenuPosition); +	updateMenuOrigin(); +} -		updateMenuOrigin(); -	} +LLMenuButton::~LLMenuButton() +{ +	cleanup();  }  boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) @@ -80,9 +74,7 @@ boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_sign  void LLMenuButton::hideMenu()  { -	if(mMenuHandle.isDead()) return; - -	LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); +	LLToggleableMenu* menu = getMenu();  	if (menu)  	{  		menu->setVisible(FALSE); @@ -94,19 +86,39 @@ LLToggleableMenu* LLMenuButton::getMenu()  	return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());  } -void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/) +void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition position /*MP_TOP_LEFT*/) +{ +	if (menu_filename.empty()) +	{ +		return; +	} + +	LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); +	if (!menu) +	{ +		llwarns << "Error loading menu_button menu" << llendl; +		return; +	} + +	setMenu(menu, position, true); +} + +void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/, bool take_ownership /*false*/)  {  	if (!menu) return; +	cleanup(); // destroy the previous memnu if we own it +  	mMenuHandle = menu->getHandle();  	mMenuPosition = position; +	mOwnMenu = take_ownership;  	menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));  }  BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )  { -	if (mMenuHandle.isDead()) return FALSE; +	if (!getMenu()) return FALSE;  	if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))  	{ @@ -118,7 +130,7 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )  		return TRUE;  	} -	LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); +	LLToggleableMenu* menu = getMenu();  	if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)  	{  		menu->setVisible(FALSE); @@ -139,9 +151,12 @@ BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)  void LLMenuButton::toggleMenu()  { -	if(mMenuHandle.isDead()) return; +	if (mValidateSignal && !(*mValidateSignal)(this, LLSD())) +	{ +		return; +	} -	LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); +	LLToggleableMenu* menu = getMenu();  	if (!menu) return;  	// Store the button rectangle to toggle menu visibility if a mouse event @@ -170,7 +185,8 @@ void LLMenuButton::toggleMenu()  void LLMenuButton::updateMenuOrigin()  { -	if (mMenuHandle.isDead()) return; +	LLToggleableMenu* menu = getMenu(); +	if (!menu) return;  	LLRect rect = getRect(); @@ -179,12 +195,12 @@ void LLMenuButton::updateMenuOrigin()  		case MP_TOP_LEFT:  		{  			mX = rect.mLeft; -			mY = rect.mTop + mMenuHandle.get()->getRect().getHeight(); +			mY = rect.mTop + menu->getRect().getHeight();  			break;  		}  		case MP_TOP_RIGHT:  		{ -			const LLRect& menu_rect = mMenuHandle.get()->getRect(); +			const LLRect& menu_rect = menu->getRect();  			mX = rect.mRight - menu_rect.getWidth();  			mY = rect.mTop + menu_rect.getHeight();  			break; @@ -211,3 +227,11 @@ void LLMenuButton::onMenuVisibilityChange(const LLSD& param)  		mIsMenuShown = false;  	}  } + +void LLMenuButton::cleanup() +{ +	if (mMenuHandle.get() && mOwnMenu) +	{ +		mMenuHandle.get()->die(); +	} +} diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index e2396e7fb2..67ec1983b3 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -34,6 +34,8 @@ class LLToggleableMenu;  class LLMenuButton  : public LLButton  { +	LOG_CLASS(LLMenuButton); +  public:  	typedef enum e_menu_position  	{ @@ -53,7 +55,7 @@ public:  	{  		// filename for it's toggleable menu  		Optional<std::string>	menu_filename; -		Optional<EMenuPosition>	position; +		Optional<EMenuPosition, MenuPositions>	position;  		Params();  	}; @@ -68,13 +70,15 @@ public:  	void hideMenu();  	LLToggleableMenu* getMenu(); -	void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT); +	void setMenu(const std::string& menu_filename, EMenuPosition position = MP_TOP_LEFT); +	void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT, bool take_ownership = false);  	void setMenuPosition(EMenuPosition position) { mMenuPosition = position; }  protected:  	friend class LLUICtrlFactory;  	LLMenuButton(const Params&); +	~LLMenuButton();  	void toggleMenu();  	void updateMenuOrigin(); @@ -82,11 +86,14 @@ protected:  	void onMenuVisibilityChange(const LLSD& param);  private: +	void cleanup(); +  	LLHandle<LLView>		mMenuHandle;  	bool					mIsMenuShown;  	EMenuPosition			mMenuPosition;  	S32						mX;  	S32						mY; +	bool					mOwnMenu; // true if we manage the menu lifetime  }; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index efb9848a90..5182a8cea1 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -4029,11 +4029,6 @@ BOOL LLContextMenu::handleRightMouseUp( S32 x, S32 y, MASK mask )  	return result;  } -void LLContextMenu::draw() -{ -	LLMenuGL::draw(); -} -  BOOL LLContextMenu::appendContextSubMenu(LLContextMenu *menu)  { diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 67b3e1fbe6..a9de3ef937 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -668,8 +668,6 @@ public:  	// can't set visibility directly, must call show or hide  	virtual void	setVisible			(BOOL visible); -	virtual void	draw				(); -	  	virtual void	show				(S32 x, S32 y, LLView* spawning_view = NULL);  	virtual void	hide				(); diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index aa5f577897..02ff64dbc6 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -173,7 +173,7 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,  	else if (floaterp->getHost())  	{  		// floaterp is hosted by somebody else and -		// this is adding it, so remove it from it's old host +		// this is adding it, so remove it from its old host  		floaterp->getHost()->removeFloater(floaterp);  	}  	else if (floaterp->getParent() == gFloaterView) @@ -188,11 +188,13 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,  	floater_data.mHeight = floaterp->getRect().getHeight();  	floater_data.mCanMinimize = floaterp->isMinimizeable();  	floater_data.mCanResize = floaterp->isResizable(); +    floater_data.mSaveRect = floaterp->mSaveRect;  	// remove minimize and close buttons  	floaterp->setCanMinimize(FALSE);  	floaterp->setCanResize(FALSE);  	floaterp->setCanDrag(FALSE); +	floaterp->mSaveRect = FALSE;  	floaterp->storeRectControl();  	// avoid double rendering of floater background (makes it more opaque)  	floaterp->setBackgroundVisible(FALSE); @@ -291,6 +293,7 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp)  	{  		LLFloaterData& floater_data = found_data_it->second;  		floaterp->setCanMinimize(floater_data.mCanMinimize); +		floaterp->mSaveRect = floater_data.mSaveRect;  		if (!floater_data.mCanResize)  		{  			// restore original size @@ -468,23 +471,12 @@ BOOL LLMultiFloater::postBuild()  void LLMultiFloater::updateResizeLimits()  { -	static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); -	const LLFloater::Params& default_params = LLFloater::getDefaultParams(); -	S32 floater_header_size = default_params.header_height; -	S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;  	// initialize minimum size constraint to the original xml values.  	S32 new_min_width = mOrigMinWidth;  	S32 new_min_height = mOrigMinHeight; -	// possibly increase minimum size constraint due to children's minimums. -	for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) -	{ -		LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); -		if (floaterp) -		{ -			new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); -			new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height); -		} -	} + +	computeResizeLimits(new_min_width, new_min_height); +  	setResizeLimits(new_min_width, new_min_height);  	S32 cur_height = getRect().getHeight(); @@ -510,3 +502,22 @@ void LLMultiFloater::updateResizeLimits()  		gFloaterView->adjustToFitScreen(this, TRUE);  	}  } + +void LLMultiFloater::computeResizeLimits(S32& new_min_width, S32& new_min_height) +{ +	static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); +	const LLFloater::Params& default_params = LLFloater::getDefaultParams(); +	S32 floater_header_size = default_params.header_height; +	S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; + +	// possibly increase minimum size constraint due to children's minimums. +	for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +	{ +		LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); +		if (floaterp) +		{ +			new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); +			new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height); +		} +	} +} diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index 9fa917eca1..d992212650 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -45,8 +45,8 @@ public:  	virtual BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key); -	/*virtual*/ void draw(); -	/*virtual*/ void setVisible(BOOL visible); +	virtual void draw(); +	virtual void setVisible(BOOL visible);  	/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);  	/*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); @@ -79,10 +79,11 @@ public:  protected:  	struct LLFloaterData  	{ -		S32		mWidth; -		S32		mHeight; -		BOOL	mCanMinimize; -		BOOL	mCanResize; +		S32		    mWidth; +		S32		    mHeight; +		BOOL	    mCanMinimize; +		BOOL	    mCanResize; +		BOOL        mSaveRect;  	};  	LLTabContainer*		mTabContainer; @@ -93,6 +94,9 @@ protected:  	LLTabContainer::TabPosition mTabPos;  	BOOL				mAutoResize;  	S32					mOrigMinWidth, mOrigMinHeight;  // logically const but initialized late + +private: +	virtual void computeResizeLimits(S32& new_min_width, S32& new_min_height);  };  #endif  // LL_MULTI_FLOATER_H diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 629eef2c3b..fdd45bd76f 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -60,7 +60,8 @@ void NotificationPriorityValues::declareValues()  }  LLNotificationForm::FormElementBase::FormElementBase() -:	name("name") +:	name("name"), +	enabled("enabled", true)  {}  LLNotificationForm::FormIgnore::FormIgnore() @@ -104,39 +105,7 @@ LLNotificationForm::Params::Params()  	form_elements("")  {} -// Local channel for persistent notifications -// Stores only persistent notifications. -// Class users can use connectChanged() to process persistent notifications -// (see LLNotificationStorage for example). -class LLPersistentNotificationChannel : public LLNotificationChannel -{ -	LOG_CLASS(LLPersistentNotificationChannel); -public: -	LLPersistentNotificationChannel() : -		LLNotificationChannel("Persistent", "Visible", ¬ificationFilter, LLNotificationComparators::orderByUUID()) -	{ -	} - -private: - -	// The channel gets all persistent notifications except those that have been canceled -	static bool notificationFilter(LLNotificationPtr pNotification) -	{ -		bool handle_notification = false; - -		handle_notification = pNotification->isPersistent() -			&& !pNotification->isCancelled(); - -		return handle_notification; -	} -	void onDelete(LLNotificationPtr pNotification) -	{ -		// we want to keep deleted notifications in our log, otherwise some  -		// notifications will be lost on exit. -		mItems.insert(pNotification); -	} -};  bool filterIgnoredNotifications(LLNotificationPtr notification)  { @@ -210,6 +179,14 @@ LLNotificationForm::LLNotificationForm()  {  } +LLNotificationForm::LLNotificationForm( const LLNotificationForm& other ) +{ +	mFormData 	   = other.mFormData; +	mIgnore 	   = other.mIgnore; +	mIgnoreMsg 	   = other.mIgnoreMsg; +	mIgnoreSetting = other.mIgnoreSetting; +	mInvertSetting = other.mInvertSetting; +}  LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p)   :	mIgnore(IGNORE_NO), @@ -246,14 +223,6 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica  	LLParamSDParser parser;  	parser.writeSD(mFormData, p.form_elements); -	if (!mFormData.isArray()) -	{ -		// change existing contents to a one element array -		LLSD new_llsd_array = LLSD::emptyArray(); -		new_llsd_array.append(mFormData); -		mFormData = new_llsd_array; -	} -  	for (LLSD::array_iterator it = mFormData.beginArray(), end_it = mFormData.endArray();  		it != end_it;  		++it) @@ -300,7 +269,7 @@ LLSD LLNotificationForm::getElement(const std::string& element_name)  } -bool LLNotificationForm::hasElement(const std::string& element_name) +bool LLNotificationForm::hasElement(const std::string& element_name) const  {  	for (LLSD::array_const_iterator it = mFormData.beginArray();  		it != mFormData.endArray(); @@ -311,7 +280,36 @@ bool LLNotificationForm::hasElement(const std::string& element_name)  	return false;  } -void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value) +bool LLNotificationForm::getElementEnabled(const std::string& element_name) const +{ +	for (LLSD::array_const_iterator it = mFormData.beginArray(); +		it != mFormData.endArray(); +		++it) +	{ +		if ((*it)["name"].asString() == element_name) +		{ +			return (*it)["enabled"].asBoolean(); +		} +	} + +	return false; +} + +void LLNotificationForm::setElementEnabled(const std::string& element_name, bool enabled) +{ +	for (LLSD::array_iterator it = mFormData.beginArray(); +		it != mFormData.endArray(); +		++it) +	{ +		if ((*it)["name"].asString() == element_name) +		{ +			(*it)["enabled"] = enabled; +		} +	} +} + + +void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value, bool enabled)  {  	LLSD element;  	element["type"] = type; @@ -319,6 +317,7 @@ void LLNotificationForm::addElement(const std::string& type, const std::string&  	element["text"] = name;  	element["value"] = value;  	element["index"] = mFormData.size(); +	element["enabled"] = enabled;  	mFormData.append(element);  } @@ -408,9 +407,13 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par  	mURLOption(p.url.option),  	mURLTarget(p.url.target),  	mUnique(p.unique.isProvided()), +	mCombineBehavior(p.unique.combine),  	mPriority(p.priority),  	mPersist(p.persist), -	mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()) +	mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), +	mLogToChat(p.log_to_chat), +	mLogToIM(p.log_to_im), +	mShowToast(p.show_toast)  {  	if (p.sound.isProvided()  		&& LLUI::sSettingGroups["config"]->controlExists(p.sound)) @@ -460,18 +463,18 @@ LLNotificationVisibilityRule::LLNotificationVisibilityRule(const LLNotificationV  	}  } -LLNotification::LLNotification(const LLNotification::Params& p) :  +LLNotification::LLNotification(const LLSDParamAdapter<Params>& p) :   	mTimestamp(p.time_stamp),   	mSubstitutions(p.substitutions),  	mPayload(p.payload), -	mExpiresAt(0), +	mExpiresAt(p.expiry),  	mTemporaryResponder(false),  	mRespondedTo(false),  	mPriority(p.priority),  	mCancelled(false),  	mIgnored(false),  	mResponderObj(NULL), -	mIsReusable(false) +	mId(p.id.isProvided() ? p.id : LLUUID::generateNewID())  {  	if (p.functor.name.isChosen())  	{ @@ -494,52 +497,32 @@ LLNotification::LLNotification(const LLNotification::Params& p) :  		mResponderObj = p.responder;  	} -	mId.generate();  	init(p.name, p.form_elements);  } -LLNotification::LLNotification(const LLSD& sd) : -	mTemporaryResponder(false), -	mRespondedTo(false), -	mCancelled(false), -	mIgnored(false), -	mResponderObj(NULL), -	mIsReusable(false) -{  -	mId.generate(); -	mSubstitutions = sd["substitutions"]; -	mPayload = sd["payload"];  -	mTimestamp = sd["time"];  -	mExpiresAt = sd["expiry"]; -	mPriority = (ENotificationPriority)sd["priority"].asInteger(); -	mResponseFunctorName = sd["responseFunctor"].asString(); -	std::string templatename = sd["name"].asString(); -	init(templatename, LLSD()); -	// replace form with serialized version -	mForm = LLNotificationFormPtr(new LLNotificationForm(sd["form"])); -} - -  LLSD LLNotification::asLLSD()  { -	LLSD output; -	output["id"] = mId; -	output["name"] = mTemplatep->mName; -	output["form"] = getForm()->asLLSD(); -	output["substitutions"] = mSubstitutions; -	output["payload"] = mPayload; -	output["time"] = mTimestamp; -	output["expiry"] = mExpiresAt; -	output["priority"] = (S32)mPriority; -	output["responseFunctor"] = mResponseFunctorName; -	output["reusable"] = mIsReusable; +	LLParamSDParser parser; -	if(mResponder) +	Params p; +	p.id = mId; +	p.name = mTemplatep->mName; +	p.form_elements = getForm()->asLLSD(); +	 +	p.substitutions = mSubstitutions; +	p.payload = mPayload; +	p.time_stamp = mTimestamp; +	p.expiry = mExpiresAt; +	p.priority = mPriority; + +	if(!mResponseFunctorName.empty())  	{ -		output["responder"] = mResponder->asLLSD(); +		p.functor.name = mResponseFunctorName;  	} +	LLSD output; +	parser.writeSD(output, p);  	return output;  } @@ -569,7 +552,6 @@ void LLNotification::updateFrom(LLNotificationPtr other)  	mRespondedTo = other->mRespondedTo;  	mResponse = other->mResponse;  	mTemporaryResponder = other->mTemporaryResponder; -	mIsReusable = other->isReusable();  	update();  } @@ -668,7 +650,7 @@ void LLNotification::respond(const LLSD& response)  		return;  	} -	if (mTemporaryResponder && !isReusable()) +	if (mTemporaryResponder)  	{  		LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);  		mResponseFunctorName = ""; @@ -897,6 +879,44 @@ std::string LLNotification::getURL() const  	return (mTemplatep ? url : "");  } +bool LLNotification::canLogToChat() const +{ +	return mTemplatep->mLogToChat; +} + +bool LLNotification::canLogToIM() const +{ +	return mTemplatep->mLogToIM; +} + +bool LLNotification::canShowToast() const +{ +	return mTemplatep->mShowToast; +} + +bool LLNotification::hasFormElements() const +{ +	return mTemplatep->mForm->getNumElements() != 0; +} + +LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const +{ +	return mTemplatep->mCombineBehavior; +} + +void LLNotification::updateForm( const LLNotificationFormPtr& form ) +{ +	mForm = form; +} + +void LLNotification::repost() +{ +	mRespondedTo = false; +	LLNotifications::instance().update(shared_from_this()); +} + + +  // =========================================================  // LLNotificationChannel implementation  // --- @@ -957,7 +977,7 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  	std::string cmd = payload["sigtype"];  	LLNotificationSet::iterator foundItem = mItems.find(pNotification);  	bool wasFound = (foundItem != mItems.end()); -	bool passesFilter = mFilter(pNotification); +	bool passesFilter = mFilter ? mFilter(pNotification) : true;  	// first, we offer the result of the filter test to the simple  	// signals for pass/fail. One of these is guaranteed to be called. @@ -987,8 +1007,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  		{  			// not in our list, add it and say so  			mItems.insert(pNotification); -			abortProcessing = mChanged(payload);  			onLoad(pNotification); +			abortProcessing = mChanged(payload);  		}  	}  	else if (cmd == "change") @@ -1003,18 +1023,18 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  			{  				// it already existed, so this is a change  				// since it changed in place, all we have to do is resend the signal -				abortProcessing = mChanged(payload);  				onChange(pNotification); +				abortProcessing = mChanged(payload);  			}  			else  			{  				// not in our list, add it and say so  				mItems.insert(pNotification); +				onChange(pNotification);  				// our payload is const, so make a copy before changing it  				LLSD newpayload = payload;  				newpayload["sigtype"] = "add";  				abortProcessing = mChanged(newpayload); -				onChange(pNotification);  			}  		}  		else @@ -1023,11 +1043,11 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  			{  				// it already existed, so this is a delete  				mItems.erase(pNotification); +				onChange(pNotification);  				// our payload is const, so make a copy before changing it  				LLSD newpayload = payload;  				newpayload["sigtype"] = "delete";  				abortProcessing = mChanged(newpayload); -				onChange(pNotification);  			}  			// didn't pass, not on our list, do nothing  		} @@ -1041,8 +1061,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  		{  			// not in our list, add it and say so  			mItems.insert(pNotification); -			abortProcessing = mChanged(payload);  			onAdd(pNotification); +			abortProcessing = mChanged(payload);  		}  	}  	else if (cmd == "delete") @@ -1050,65 +1070,35 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  		// if we have it in our list, pass on the delete, then delete it, else do nothing  		if (wasFound)  		{ +			onDelete(pNotification);  			abortProcessing = mChanged(payload); -			// do not delete the notification to make LLChatHistory::appendMessage add notification panel to IM window -			if( ! pNotification->isReusable() ) -			{ -				mItems.erase(pNotification); -				onDelete(pNotification); -			} +			mItems.erase(pNotification);  		}  	}  	return abortProcessing;  } -/* static */ -LLNotificationChannelPtr LLNotificationChannel::buildChannel(const std::string& name,  -															 const std::string& parent, -															 LLNotificationFilter filter,  -															 LLNotificationComparator comparator) +LLNotificationChannel::LLNotificationChannel(const Params& p) +:	LLNotificationChannelBase(p.filter()), +	LLInstanceTracker<LLNotificationChannel, std::string>(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), +	mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()) +{ +	BOOST_FOREACH(const std::string& source, p.sources)  { -	// note: this is not a leak; notifications are self-registering. -	// This factory helps to prevent excess deletions by making sure all smart -	// pointers to notification channels come from the same source -	new LLNotificationChannel(name, parent, filter, comparator); -	return LLNotifications::instance().getChannel(name); +		connectToChannel(source); +	}  }  LLNotificationChannel::LLNotificationChannel(const std::string& name,   											 const std::string& parent, -											 LLNotificationFilter filter,  -											 LLNotificationComparator comparator) :  -LLNotificationChannelBase(filter, comparator), -mName(name), -mParent(parent) -{ -	// store myself in the channel map -	LLNotifications::instance().addChannel(LLNotificationChannelPtr(this)); +											 LLNotificationFilter filter)  +:	LLNotificationChannelBase(filter), +	LLInstanceTracker<LLNotificationChannel, std::string>(name), +	mName(name) +{  	// bind to notification broadcast -	if (parent.empty()) -	{ -		LLNotifications::instance().connectChanged( -			boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); -	} -	else -	{ -		LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent); -		p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); -	} -} - - -void LLNotificationChannel::setComparator(LLNotificationComparator comparator)  -{  -	mComparator = comparator;  -	LLNotificationSet s2(mComparator); -	s2.insert(mItems.begin(), mItems.end()); -	mItems.swap(s2); -	 -	// notify clients that we've been resorted -	mChanged(LLSD().with("sigtype", "sort"));  +	connectToChannel(parent);  }  bool LLNotificationChannel::isEmpty() const @@ -1126,6 +1116,11 @@ LLNotificationChannel::Iterator LLNotificationChannel::end()  	return mItems.end();  } +size_t LLNotificationChannel::size() +{ +	return mItems.size(); +} +  std::string LLNotificationChannel::summarize()  {  	std::string s("Channel '"); @@ -1139,18 +1134,31 @@ std::string LLNotificationChannel::summarize()  	return s;  } +void LLNotificationChannel::connectToChannel( const std::string& channel_name ) +{ +	if (channel_name.empty()) +	{ +		LLNotifications::instance().connectChanged( +			boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); +	} +	else +	{ +		LLNotificationChannelPtr p = LLNotifications::instance().getChannel(channel_name); +		p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); +	} +}  // ---  // END OF LLNotificationChannel implementation  // ========================================================= -// ========================================================= +// ==============================================	===========  // LLNotifications implementation  // --- -LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything, -															   LLNotificationComparators::orderByUUID()), -									mIgnoreAllNotifications(false) +LLNotifications::LLNotifications()  +:	LLNotificationChannelBase(LLNotificationFilters::includeEverything), +	mIgnoreAllNotifications(false)  {  	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2)); @@ -1191,7 +1199,15 @@ bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif)  		if (pNotif != existing_notification   			&& pNotif->isEquivalentTo(existing_notification))  		{ -			return false; +			if (pNotif->getCombineBehavior() == LLNotification::CANCEL_OLD) +			{ +				cancel(existing_notification); +				return true; +			} +			else +			{ +				return false; +			}  		}  	} @@ -1231,43 +1247,43 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload)  		return false;  	} -	// Update the existing unique notification with the data from this particular instance... -	// This guarantees that duplicate notifications will be collapsed to the one -	// most recently triggered -	for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); -		existing_it != mUniqueNotifications.end(); -		++existing_it) +	switch(pNotif->getCombineBehavior())  	{ -		LLNotificationPtr existing_notification = existing_it->second; -		if (pNotif != existing_notification  -			&& pNotif->isEquivalentTo(existing_notification)) +	case  LLNotification::REPLACE_WITH_NEW: +		// Update the existing unique notification with the data from this particular instance... +		// This guarantees that duplicate notifications will be collapsed to the one +		// most recently triggered +		for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); +			existing_it != mUniqueNotifications.end(); +			++existing_it)  		{ -			// copy notification instance data over to oldest instance -			// of this unique notification and update it -			existing_notification->updateFrom(pNotif); -			// then delete the new one -			cancel(pNotif); +			LLNotificationPtr existing_notification = existing_it->second; +			if (pNotif != existing_notification  +				&& pNotif->isEquivalentTo(existing_notification)) +			{ +				// copy notification instance data over to oldest instance +				// of this unique notification and update it +				existing_notification->updateFrom(pNotif); +				// then delete the new one +				cancel(pNotif); +			}  		} +		break; +	case LLNotification::KEEP_OLD: +		break; +	case LLNotification::CANCEL_OLD: +		// already handled by filter logic +		break; +	default: +		break;  	}  	return false;  } - -void LLNotifications::addChannel(LLNotificationChannelPtr pChan) -{ -	mChannels[pChan->getName()] = pChan; -} -  LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName)  { -	ChannelMap::iterator p = mChannels.find(channelName); -	if(p == mChannels.end()) -	{ -		llerrs << "Did not find channel named " << channelName << llendl; -		return LLNotificationChannelPtr(); -	} -	return p->second; +	return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName));  } @@ -1283,24 +1299,21 @@ void LLNotifications::createDefaultChannels()  {  	// now construct the various channels AFTER loading the notifications,  	// because the history channel is going to rewrite the stored notifications file -	LLNotificationChannel::buildChannel("Enabled", "", -		!boost::bind(&LLNotifications::getIgnoreAllNotifications, this)); -	LLNotificationChannel::buildChannel("Expiration", "Enabled", -		boost::bind(&LLNotifications::expirationFilter, this, _1)); -	LLNotificationChannel::buildChannel("Unexpired", "Enabled", -		!boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind -	LLNotificationChannel::buildChannel("Unique", "Unexpired", -		boost::bind(&LLNotifications::uniqueFilter, this, _1)); -	LLNotificationChannel::buildChannel("Ignore", "Unique", -		filterIgnoredNotifications); -	LLNotificationChannel::buildChannel("VisibilityRules", "Ignore", -		boost::bind(&LLNotifications::isVisibleByRules, this, _1)); -	LLNotificationChannel::buildChannel("Visible", "VisibilityRules", -		&LLNotificationFilters::includeEverything); - -	// create special persistent notification channel -	// this isn't a leak, don't worry about the empty "new" -	new LLPersistentNotificationChannel(); +	mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "", +		!boost::bind(&LLNotifications::getIgnoreAllNotifications, this))); +	mDefaultChannels.push_back(new LLNotificationChannel("Expiration", "Enabled", +		boost::bind(&LLNotifications::expirationFilter, this, _1))); +	mDefaultChannels.push_back(new LLNotificationChannel("Unexpired", "Enabled", +		!boost::bind(&LLNotifications::expirationFilter, this, _1))); // use negated bind +	mDefaultChannels.push_back(new LLNotificationChannel("Unique", "Unexpired", +		boost::bind(&LLNotifications::uniqueFilter, this, _1))); +	mDefaultChannels.push_back(new LLNotificationChannel("Ignore", "Unique", +		filterIgnoredNotifications)); +	mDefaultChannels.push_back(new LLNotificationChannel("VisibilityRules", "Ignore", +		boost::bind(&LLNotifications::isVisibleByRules, this, _1))); +	mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules", +		&LLNotificationFilters::includeEverything)); +	mDefaultChannels.push_back(new LLPersistentNotificationChannel());  	// connect action methods to these channels  	LLNotifications::instance().getChannel("Enabled")-> @@ -1536,34 +1549,32 @@ void LLNotifications::addFromCallback(const LLSD& name)  	add(name.asString(), LLSD(), LLSD());  } -LLNotificationPtr LLNotifications::add(const std::string& name,  -									   const LLSD& substitutions,  -									   const LLSD& payload) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload)  {  	LLNotification::Params::Functor functor_p;  	functor_p.name = name;  	return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));	  } -LLNotificationPtr LLNotifications::add(const std::string& name,  -									   const LLSD& substitutions,  -									   const LLSD& payload,  -									   const std::string& functor_name) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, const std::string& functor_name)  {  	LLNotification::Params::Functor functor_p;  	functor_p.name = functor_name; -	return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));	 +	return add(LLNotification::Params().name(name) +										.substitutions(substitutions) +										.payload(payload) +										.functor(functor_p));	  }  //virtual -LLNotificationPtr LLNotifications::add(const std::string& name,  -										const LLSD& substitutions,  -										const LLSD& payload,  -										LLNotificationFunctorRegistry::ResponseFunctor functor) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, LLNotificationFunctorRegistry::ResponseFunctor functor)  {  	LLNotification::Params::Functor functor_p;  	functor_p.function = functor; -	return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));	 +	return add(LLNotification::Params().name(name) +										.substitutions(substitutions) +										.payload(payload) +										.functor(functor_p));	  }  // generalized add function that takes a parameter block object for more complex instantiations @@ -1594,12 +1605,11 @@ void LLNotifications::cancel(LLNotificationPtr pNotif)  	if (pNotif == NULL || pNotif->isCancelled()) return;  	LLNotificationSet::iterator it=mItems.find(pNotif); -	if (it == mItems.end()) +	if (it != mItems.end())  	{ -		llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl; +		pNotif->cancel(); +		updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);  	} -	pNotif->cancel(); -	updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);  }  void LLNotifications::cancelByName(const std::string& name) @@ -1638,7 +1648,7 @@ void LLNotifications::update(const LLNotificationPtr pNotif)  LLNotificationPtr LLNotifications::find(LLUUID uuid)  { -	LLNotificationPtr target = LLNotificationPtr(new LLNotification(uuid)); +	LLNotificationPtr target = LLNotificationPtr(new LLNotification(LLNotification::Params().id(uuid)));  	LLNotificationSet::iterator it=mItems.find(target);  	if (it == mItems.end())  	{ diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 4ae02b943f..19b30b8973 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -88,16 +88,14 @@  #include <boost/enable_shared_from_this.hpp>  #include <boost/type_traits.hpp> -// we want to minimize external dependencies, but this one is important -#include "llsd.h" - -// and we need this to manage the notification callbacks  #include "llevents.h"  #include "llfunctorregistry.h" -#include "llpointer.h"  #include "llinitparam.h"  #include "llnotificationslistener.h"  #include "llnotificationptr.h" +#include "llpointer.h" +#include "llrefcount.h" +#include "llsdparam.h"  class LLAvatarName;  typedef enum e_notification_priority @@ -164,6 +162,7 @@ public:  	struct FormElementBase : public LLInitParam::Block<FormElementBase>  	{  		Optional<std::string>	name; +		Optional<bool>			enabled;  		FormElementBase();  	}; @@ -233,16 +232,20 @@ public:  	} EIgnoreType;  	LLNotificationForm(); +	LLNotificationForm(const LLNotificationForm&);  	LLNotificationForm(const LLSD& sd);  	LLNotificationForm(const std::string& name, const Params& p); +	void fromLLSD(const LLSD& sd);  	LLSD asLLSD() const;  	S32 getNumElements() { return mFormData.size(); }  	LLSD getElement(S32 index) { return mFormData.get(index); }  	LLSD getElement(const std::string& element_name); -	bool hasElement(const std::string& element_name); -	void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD()); +	bool hasElement(const std::string& element_name) const; +	bool getElementEnabled(const std::string& element_name) const; +	void setElementEnabled(const std::string& element_name, bool enabled); +	void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true);  	void formatElements(const LLSD& substitutions);  	// appends form elements from another form serialized as LLSD  	void append(const LLSD& sub_form); @@ -296,19 +299,20 @@ LOG_CLASS(LLNotification);  friend class LLNotifications;  public: +  	// parameter object used to instantiate a new notification  	struct Params : public LLInitParam::Block<Params>  	{  		friend class LLNotification;  		Mandatory<std::string>					name; - -		// optional -		Optional<LLSD>							substitutions; -		Optional<LLSD>							payload; +		Optional<LLUUID>						id; +		Optional<LLSD>							substitutions, +												form_elements, +												payload;  		Optional<ENotificationPriority, NotificationPriorityValues>	priority; -		Optional<LLSD>							form_elements; -		Optional<LLDate>						time_stamp; +		Optional<LLDate>						time_stamp, +												expiry;  		Optional<LLNotificationContext*>		context;  		Optional<void*>							responder; @@ -319,7 +323,7 @@ public:  			Alternative<LLNotificationResponderPtr>						responder;  			Functor() -			:	name("functor_name"), +			:	name("responseFunctor"),  				function("functor"),  				responder("responder")  			{} @@ -328,10 +332,13 @@ public:  		Params()  		:	name("name"), +			id("id"),  			priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), -			time_stamp("time_stamp"), +			time_stamp("time"),  			payload("payload"), -			form_elements("form_elements") +			form_elements("form"), +			substitutions("substitutions"), +			expiry("expiry")  		{  			time_stamp = LLDate::now();  			responder = NULL; @@ -340,9 +347,11 @@ public:  		Params(const std::string& _name)   		:	name("name"),  			priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), -			time_stamp("time_stamp"), +			time_stamp("time"),  			payload("payload"), -			form_elements("form_elements") +			form_elements("form"), +			substitutions("substitutions"), +			expiry("expiry")  		{  			functor.name = _name;  			name = _name; @@ -355,7 +364,7 @@ public:  private: -	LLUUID mId; +	const LLUUID mId;  	LLSD mPayload;  	LLSD mSubstitutions;  	LLDate mTimestamp; @@ -367,7 +376,6 @@ private:  	ENotificationPriority mPriority;  	LLNotificationFormPtr mForm;  	void* mResponderObj; // TODO - refactor/remove this field -	bool mIsReusable;  	LLNotificationResponderPtr mResponder;  	// a reference to the template @@ -392,18 +400,10 @@ private:  	void init(const std::string& template_name, const LLSD& form_elements); -	LLNotification(const Params& p); - -	// this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT -	// for anything real! - LLNotification(LLUUID uuid) : mId(uuid), mCancelled(false), mRespondedTo(false), mIgnored(false), mPriority(NOTIFICATION_PRIORITY_UNSPECIFIED), mTemporaryResponder(false) {} -  	void cancel();  public: - -	// constructor from a saved notification -	LLNotification(const LLSD& sd); +	LLNotification(const LLSDParamAdapter<Params>& p);  	void setResponseFunctor(std::string const &responseFunctorName); @@ -448,6 +448,11 @@ public:  	// ["responseFunctor"] = name of registered functor that handles responses to notification;  	LLSD asLLSD(); +	const LLNotificationFormPtr getForm(); +	void updateForm(const LLNotificationFormPtr& form); + +	void repost(); +  	void respond(const LLSD& sd);  	void respondWithDefault(); @@ -514,8 +519,20 @@ public:  	std::string getURL() const;  	S32 getURLOption() const;      S32 getURLOpenExternally() const; +	bool canLogToChat() const; +	bool canLogToIM() const; +	bool canShowToast() const; +	bool hasFormElements() const; + +	typedef enum e_combine_behavior +	{ +		REPLACE_WITH_NEW, +		KEEP_OLD, +		CANCEL_OLD + +	} ECombineBehavior; -	const LLNotificationFormPtr getForm(); +	ECombineBehavior getCombineBehavior() const;  	const LLDate getExpiration() const  	{ @@ -532,10 +549,6 @@ public:  		return mId;  	} -	bool isReusable() { return mIsReusable; } - -	void setReusable(bool reusable) { mIsReusable = reusable; } -	  	// comparing two notifications normally means comparing them by UUID (so we can look them  	// up quickly this way)  	bool operator<(const LLNotification& rhs) const @@ -647,44 +660,18 @@ namespace LLNotificationFilters  namespace LLNotificationComparators  { -	typedef enum e_direction { ORDER_DECREASING, ORDER_INCREASING } EDirection; - -	// generic order functor that takes method or member variable reference -	template<typename T> -	struct orderBy +	struct orderByUUID  	{ -		typedef boost::function<T (LLNotificationPtr)> field_t; -        	orderBy(field_t field, EDirection direction = ORDER_INCREASING) : mField(field), mDirection(direction) {}  		bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs)  		{ -			if (mDirection == ORDER_DECREASING) -			{ -				return mField(lhs) > mField(rhs); -			} -			else -			{ -				return mField(lhs) < mField(rhs); -			} +			return lhs->id() < rhs->id();  		} - -		field_t mField; -		EDirection mDirection; -	}; - -	struct orderByUUID : public orderBy<const LLUUID&> -	{ -		orderByUUID(EDirection direction = ORDER_INCREASING) : orderBy<const LLUUID&>(&LLNotification::id, direction) {} -	}; - -	struct orderByDate : public orderBy<const LLDate&> -	{ -		orderByDate(EDirection direction = ORDER_INCREASING) : orderBy<const LLDate&>(&LLNotification::getDate, direction) {}  	};  };  typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter;  typedef boost::function<bool (LLNotificationPtr, LLNotificationPtr)> LLNotificationComparator; -typedef std::set<LLNotificationPtr, LLNotificationComparator> LLNotificationSet; +typedef std::set<LLNotificationPtr, LLNotificationComparators::orderByUUID> LLNotificationSet;  typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap;  // ======================================================== @@ -705,12 +692,14 @@ typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap;  // all of the built-in tests should attach to the "Visible" channel  //  class LLNotificationChannelBase : -	public LLEventTrackable +	public LLEventTrackable, +	public LLRefCount  {  	LOG_CLASS(LLNotificationChannelBase);  public: -	LLNotificationChannelBase(LLNotificationFilter filter, LLNotificationComparator comp) :  -		mFilter(filter), mItems(comp)  +	LLNotificationChannelBase(LLNotificationFilter filter)  +	:	mFilter(filter),  +		mItems()   	{}  	virtual ~LLNotificationChannelBase() {}  	// you can also connect to a Channel, so you can be notified of @@ -785,59 +774,49 @@ protected:  // destroy it, but if it becomes necessary to do so, the shared_ptr model  // will ensure that we don't leak resources.  class LLNotificationChannel; -typedef boost::shared_ptr<LLNotificationChannel> LLNotificationChannelPtr; +typedef boost::intrusive_ptr<LLNotificationChannel> LLNotificationChannelPtr;  // manages a list of notifications  // Note that if this is ever copied around, we might find ourselves with multiple copies  // of a queue with notifications being added to different nonequivalent copies. So we  -// make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it. -//  -// NOTE: LLNotificationChannel is self-registering. The *correct* way to create one is to  -// do something like: -//		LLNotificationChannel::buildChannel("name", "parent"...); -// This returns an LLNotificationChannelPtr, which you can store, or -// you can then retrieve the channel by using the registry: -//		LLNotifications::instance().getChannel("name")... +// make it inherit from boost::noncopyable, and then create a map of LLPointer to manage it.  //  class LLNotificationChannel :   	boost::noncopyable,  -	public LLNotificationChannelBase +	public LLNotificationChannelBase, +	public LLInstanceTracker<LLNotificationChannel, std::string>  {  	LOG_CLASS(LLNotificationChannel);  public:   +	// Notification Channels have a filter, which determines which notifications +	// will be added to this channel.  +	// Channel filters cannot change. +	struct Params : public LLInitParam::Block<Params> +	{ +		Mandatory<std::string>				name; +		Optional<LLNotificationFilter>		filter; +		Multiple<std::string>				sources; +	}; + +	LLNotificationChannel(const Params& p = Params()); +	LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter); +  	virtual ~LLNotificationChannel() {}  	typedef LLNotificationSet::iterator Iterator;  	std::string getName() const { return mName; } -	std::string getParentChannelName() { return mParent; } +     +	void connectToChannel(const std::string& channel_name);      bool isEmpty() const;      Iterator begin();      Iterator end(); +	size_t size(); -    // Channels have a comparator to control sort order; -	// the default sorts by arrival date -    void setComparator(LLNotificationComparator comparator); -	  	std::string summarize(); -	// factory method for constructing these channels; since they're self-registering, -	// we want to make sure that you can't use new to make them -	static LLNotificationChannelPtr buildChannel(const std::string& name, const std::string& parent, -						LLNotificationFilter filter=LLNotificationFilters::includeEverything,  -						LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); -	 -protected: -    // Notification Channels have a filter, which determines which notifications -	// will be added to this channel.  -	// Channel filters cannot change. -	// Channels have a protected constructor so you can't make smart pointers that don't  -	// come from our internal reference; call NotificationChannel::build(args) -	LLNotificationChannel(const std::string& name, const std::string& parent, -						  LLNotificationFilter filter, LLNotificationComparator comparator); -  private:  	std::string mName;  	std::string mParent; @@ -924,10 +903,6 @@ public:  	void createDefaultChannels(); -	typedef std::map<std::string, LLNotificationChannelPtr> ChannelMap; -	ChannelMap mChannels; - -	void addChannel(LLNotificationChannelPtr pChan);  	LLNotificationChannelPtr getChannel(const std::string& channelName);  	std::string getGlobalString(const std::string& key) const; @@ -966,6 +941,7 @@ private:  	bool mIgnoreAllNotifications;      boost::scoped_ptr<LLNotificationsListener> mListener; +	std::vector<LLNotificationChannelPtr> mDefaultChannels;  };  /** @@ -1028,5 +1004,56 @@ protected:  	std::string mName;  }; +// Stores only persistent notifications. +// Class users can use connectChanged() to process persistent notifications +// (see LLNotificationStorage for example). +class LLPersistentNotificationChannel : public LLNotificationChannel +{ +	LOG_CLASS(LLPersistentNotificationChannel); +public: +	LLPersistentNotificationChannel()  +		:	LLNotificationChannel("Persistent", "Visible", ¬ificationFilter) +	{ +	} + +	typedef std::vector<LLNotificationPtr> history_list_t; +	history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); } +	history_list_t::iterator endHistory() { return mHistory.end(); } + +private: + +	struct sortByTime +	{ +		S32 operator ()(const LLNotificationPtr& a, const LLNotificationPtr& b) +		{ +			return a->getDate() < b->getDate(); +		} +	}; + +	void sortHistory() +	{ +		std::sort(mHistory.begin(), mHistory.end(), sortByTime()); +	} + + +	// The channel gets all persistent notifications except those that have been canceled +	static bool notificationFilter(LLNotificationPtr pNotification) +	{ +		bool handle_notification = false; + +		handle_notification = pNotification->isPersistent() +			&& !pNotification->isCancelled(); + +		return handle_notification; +	} + +	void onAdd(LLNotificationPtr p)  +	{ +		mHistory.push_back(p); +	} + +	std::vector<LLNotificationPtr> mHistory; +}; +  #endif//LL_LLNOTIFICATIONS_H diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index 3bbeb3a778..e4e127336b 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -121,13 +121,13 @@ void LLNotificationsListener::listChannels(const LLSD& params) const  {      LLReqID reqID(params);      LLSD response(reqID.makeResponse()); -    for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()), -                                                     cmend(mNotifications.mChannels.end()); +    for (LLNotificationChannel::instance_iter cmi(LLNotificationChannel::beginInstances()), +                                                     cmend(LLNotificationChannel::endInstances());           cmi != cmend; ++cmi)      {          LLSD channelInfo; -        channelInfo["parent"] = cmi->second->getParentChannelName(); -        response[cmi->first] = channelInfo; +        //channelInfo["parent"] = cmi->second->getParentChannelName(); +        response[cmi->getName()] = channelInfo;      }      LLEventPumps::instance().obtain(params["reply"]).post(response);  } diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index b3b0bae862..9434efe1b9 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -61,6 +61,18 @@ typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;  // from the appropriate local language directory).  struct LLNotificationTemplate  { +	struct CombineBehaviorNames +		:	public LLInitParam::TypeValuesHelper<LLNotification::ECombineBehavior, CombineBehaviorNames> +	{ +		static void declareValues() +		{ +			declare("replace_with_new", LLNotification::REPLACE_WITH_NEW); +			declare("keep_old", LLNotification::KEEP_OLD); +			declare("cancel_old", LLNotification::CANCEL_OLD); +		} +	}; + +  	struct GlobalString : public LLInitParam::Block<GlobalString>  	{  		Mandatory<std::string>	name, @@ -94,9 +106,11 @@ struct LLNotificationTemplate  		Optional<LLInitParam::Flag>	dummy_val;  	public:  		Multiple<UniquenessContext>	contexts; +		Optional<LLNotification::ECombineBehavior, CombineBehaviorNames> combine;  		UniquenessConstraint()  		:	contexts("context"), +			combine("combine", LLNotification::REPLACE_WITH_NEW),  			dummy_val("")  		{}  	}; @@ -183,7 +197,10 @@ struct LLNotificationTemplate  	struct Params : public LLInitParam::Block<Params>  	{  		Mandatory<std::string>			name; -		Optional<bool>					persist; +		Optional<bool>					persist, +										log_to_im, +										show_toast, +										log_to_chat;  		Optional<std::string>			functor,  										icon,  										label, @@ -204,6 +221,9 @@ struct LLNotificationTemplate  		Params()  		:	name("name"),  			persist("persist", false), +			log_to_im("log_to_im", false), +			show_toast("show_toast", true), +			log_to_chat("log_to_chat", true),  			functor("functor"),  			icon("icon"),  			label("label"), @@ -262,6 +282,7 @@ struct LLNotificationTemplate      // (used for things like progress indications, or repeating warnings      // like "the grid is going down in N minutes")      bool mUnique; +	LLNotification::ECombineBehavior mCombineBehavior;      // if we want to be unique only if a certain part of the payload or substitutions args  	// are constant specify the field names for the payload. The notification will only be      // combined if all of the fields named in the context are identical in the @@ -308,6 +329,11 @@ struct LLNotificationTemplate  	LLUUID mSoundEffect;  	// List of tags that rules can match against.  	std::list<std::string> mTags; + +	// inject these notifications into chat/IM streams +	bool mLogToChat; +	bool mLogToIM; +	bool mShowToast;  };  #endif //LL_LLNOTIFICATION_TEMPLATE_H diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 802914e25b..b3499693dd 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -2720,6 +2720,11 @@ BOOL LLScrollListCtrl::hasSortOrder() const  	return !mSortColumns.empty();  } +void LLScrollListCtrl::clearSortOrder() +{ +	mSortColumns.clear(); +} +  void LLScrollListCtrl::clearColumns()  {  	column_map_t::iterator itor; diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 44d9635838..e83794e173 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -374,6 +374,7 @@ public:  	std::string     getSortColumnName();  	BOOL			getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }  	BOOL			hasSortOrder() const; +	void			clearSortOrder();  	S32		selectMultiple( uuid_vec_t ids );  	// conceptually const, but mutates mItemList diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 5fc2cc350d..d0920685bf 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1209,7 +1209,11 @@ void LLTabContainer::removeTabPanel(LLPanel* child)  				update_images(mTabList[mTabList.size()-2], mLastTabParams, getTabPosition());  			} -			removeChild( tuple->mButton ); +			if (!getTabsHidden()) +			{ +				// We need to remove tab buttons only if the tabs are not hidden. +				removeChild( tuple->mButton ); +			}   			delete tuple->mButton;   			removeChild( tuple->mTabPanel ); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 3815eec447..98624f42b9 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -145,6 +145,7 @@ LLTextBase::Params::Params()  :	cursor_color("cursor_color"),  	text_color("text_color"),  	text_readonly_color("text_readonly_color"), +	text_tentative_color("text_tentative_color"),  	bg_visible("bg_visible", false),  	border_visible("border_visible", false),  	bg_readonly_color("bg_readonly_color"), @@ -179,7 +180,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  :	LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),  	mURLClickSignal(NULL),  	mMaxTextByteLength( p.max_text_length ), -	mDefaultFont(p.font), +	mFont(p.font),  	mFontShadow(p.font_shadow),  	mPopupMenu(NULL),  	mReadOnly(p.read_only), @@ -190,6 +191,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  	mFgColor(p.text_color),  	mBorderVisible( p.border_visible ),  	mReadOnlyFgColor(p.text_readonly_color), +	mTentativeFgColor(p.text_tentative_color()),  	mWriteableBgColor(p.bg_writeable_color),  	mReadOnlyBgColor(p.bg_readonly_color),  	mFocusBgColor(p.bg_focus_color), @@ -319,21 +321,21 @@ bool LLTextBase::truncate()  	return did_truncate;  } -const LLStyle::Params& LLTextBase::getDefaultStyleParams() +const LLStyle::Params& LLTextBase::getStyleParams()  {  	//FIXME: convert mDefaultStyle to a flyweight http://www.boost.org/doc/libs/1_40_0/libs/flyweight/doc/index.html  	//and eliminate color member values  	if (mStyleDirty)  	{ -		  mDefaultStyle +		  mStyle  				  .color(LLUIColor(&mFgColor))						// pass linked color instead of copy of mFGColor  				  .readonly_color(LLUIColor(&mReadOnlyFgColor))  				  .selected_color(LLUIColor(&mTextSelectedColor)) -				  .font(mDefaultFont) +				  .font(mFont)  				  .drop_shadow(mFontShadow);  		  mStyleDirty = false;  	} -	return mDefaultStyle; +	return mStyle;  }  void LLTextBase::onValueChange(S32 start, S32 end) @@ -522,11 +524,17 @@ void LLTextBase::drawCursor()  void LLTextBase::drawText()  { -	const S32 text_len = getLength(); -	if( text_len <= 0 ) +	S32 text_len = getLength(); + +	if (text_len <= 0 && mLabel.empty())  	{  		return;  	} +	else if (text_len <= 0 && !mLabel.empty() && !hasFocus()) +	{ +		text_len = mLabel.getWString().length(); +	} +  	S32 selection_left = -1;  	S32 selection_right = -1;  	// Draw selection even if we don't have keyboard focus for search/replace @@ -770,7 +778,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s  	else  	{  		// create default editable segment to hold new text -		LLStyleConstSP sp(new LLStyle(getDefaultStyleParams())); +		LLStyleConstSP sp(new LLStyle(getStyleParams()));  		default_segment = new LLNormalTextSegment( sp, pos, pos + insert_len, *this);  	} @@ -890,7 +898,7 @@ void LLTextBase::createDefaultSegment()  	// ensures that there is always at least one segment  	if (mSegments.empty())  	{ -		LLStyleConstSP sp(new LLStyle(getDefaultStyleParams())); +		LLStyleConstSP sp(new LLStyle(getStyleParams()));  		LLTextSegmentPtr default_segment = new LLNormalTextSegment( sp, 0, getLength() + 1, *this);  		mSegments.insert(default_segment);  		default_segment->linkToDocument(this); @@ -1338,6 +1346,23 @@ void LLTextBase::onSpellCheckSettingsChange()  	mSpellCheckStart = mSpellCheckEnd = -1;  } +void LLTextBase::onFocusReceived() +{ +	if (!getLength() && !mLabel.empty()) +	{ +		// delete label which is LLLabelTextSegment +		clearSegments(); +	} +} + +void LLTextBase::onFocusLost() +{ +	if (!getLength() && !mLabel.empty()) +	{ +		resetLabel(); +	} +} +  // Sets the scrollbar from the cursor position  void LLTextBase::updateScrollFromCursor()  { @@ -1924,7 +1949,7 @@ static LLFastTimer::DeclareTimer FTM_PARSE_HTML("Parse HTML");  void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)  {  	LLStyle::Params style_params(input_params); -	style_params.fillFrom(getDefaultStyleParams()); +	style_params.fillFrom(getStyleParams());  	S32 part = (S32)LLTextParser::WHOLE;  	if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358). @@ -2009,6 +2034,39 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c  	appendTextImpl(new_text,input_params);  } +void LLTextBase::setLabel(const LLStringExplicit& label) +{ +	mLabel = label; +	resetLabel(); +} + +BOOL LLTextBase::setLabelArg(const std::string& key, const LLStringExplicit& text ) +{ +	mLabel.setArg(key, text); +	return TRUE; +} + +void LLTextBase::resetLabel() +{ +	if (!getLength() && !mLabel.empty() && !hasFocus()) +	{ +		clearSegments(); + +		LLStyle* style = new LLStyle(getStyleParams()); +		style->setColor(mTentativeFgColor); +		LLStyleConstSP sp(style); + +		LLTextSegmentPtr label = new LLLabelTextSegment(sp, 0, mLabel.getWString().length() + 1, *this); +		insertSegment(label); +	} +} + +void LLTextBase::setFont(const LLFontGL* font) +{ +	mFont = font; +	mStyleDirty = true; +} +  void LLTextBase::needsReflow(S32 index)  {  	lldebugs << "reflow on object " << (void*)this << " index = " << mReflowIndex << ", new index = " << index << llendl; @@ -2399,7 +2457,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const  	{   		// return default height rect in upper left  		local_rect = content_window_rect; -		local_rect.mBottom = local_rect.mTop - mDefaultFont->getLineHeight(); +		local_rect.mBottom = local_rect.mTop - mFont->getLineHeight();  		return local_rect;  	} @@ -2904,7 +2962,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele  {  	F32 alpha = LLViewDrawContext::getCurrentContext().mAlpha; -	const LLWString &text = mEditor.getWText(); +	const LLWString &text = getWText();  	F32 right_x = rect.mLeft;  	if (!mStyle->isVisible()) @@ -3067,7 +3125,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt  	if (num_chars > 0)  	{  		height = mFontHeight; -		const LLWString &text = mEditor.getWText(); +		const LLWString &text = getWText();  		// if last character is a newline, then return true, forcing line break  		width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);  	} @@ -3076,7 +3134,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt  S32	LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const  { -	const LLWString &text = mEditor.getWText(); +	const LLWString &text = getWText();  	return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset,  											   (F32)segment_local_x_coord,  											   F32_MAX, @@ -3086,7 +3144,7 @@ S32	LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset,  S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const  { -	const LLWString &text = mEditor.getWText(); +	const LLWString &text = getWText();  	LLUIImagePtr image = mStyle->getImage();  	if( image.notNull()) @@ -3122,7 +3180,7 @@ S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin  	S32 last_char_in_run = mStart + segment_offset + num_chars;  	// check length first to avoid indexing off end of string  	if (last_char_in_run < mEnd  -		&& (last_char_in_run >= mEditor.getLength() )) +		&& (last_char_in_run >= getLength()))  	{  		num_chars++;  	} @@ -3140,6 +3198,39 @@ void LLNormalTextSegment::dump() const  		llendl;  } +/*virtual*/ +const LLWString& LLNormalTextSegment::getWText()	const +{ +	return mEditor.getWText(); +} + +/*virtual*/ +const S32 LLNormalTextSegment::getLength() const +{ +	return mEditor.getLength(); +} + +LLLabelTextSegment::LLLabelTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor ) +:	LLNormalTextSegment(style, start, end, editor) +{ +} + +LLLabelTextSegment::LLLabelTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible) +:	LLNormalTextSegment(color, start, end, editor, is_visible) +{ +} + +/*virtual*/ +const LLWString& LLLabelTextSegment::getWText()	const +{ +	return mEditor.getWlabel(); +} +/*virtual*/ +const S32 LLLabelTextSegment::getLength() const +{ +	return mEditor.getWlabel().length(); +} +  //  // LLOnHoverChangeableTextSegment  // diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 90b147cee1..79662ebd33 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -106,7 +106,7 @@ class LLNormalTextSegment : public LLTextSegment  public:  	LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor );  	LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE); -	~LLNormalTextSegment(); +	virtual ~LLNormalTextSegment();  	/*virtual*/ bool				getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;  	/*virtual*/ S32					getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; @@ -131,6 +131,9 @@ public:  protected:  	F32					drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRect rect); +	virtual		const LLWString&	getWText()	const; +	virtual		const S32			getLength()	const; +  protected:  	class LLTextBase&	mEditor;  	LLStyleConstSP		mStyle; @@ -140,6 +143,21 @@ protected:  	boost::signals2::connection mImageLoadedConnection;  }; +// This text segment is the same as LLNormalTextSegment, the only difference +// is that LLNormalTextSegment draws value of LLTextBase (LLTextBase::getWText()), +// but LLLabelTextSegment draws label of the LLTextBase (LLTextBase::mLabel) +class LLLabelTextSegment : public LLNormalTextSegment +{ +public: +	LLLabelTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor ); +	LLLabelTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE); + +protected: + +	/*virtual*/	const LLWString&	getWText()	const; +	/*virtual*/	const S32			getLength()	const; +}; +  // Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment)  class LLOnHoverChangeableTextSegment : public LLNormalTextSegment  { @@ -251,6 +269,7 @@ public:  		Optional<LLUIColor>		cursor_color,  								text_color,  								text_readonly_color, +								text_tentative_color,  								bg_readonly_color,  								bg_writeable_color,  								bg_focus_color, @@ -314,6 +333,9 @@ public:  	/*virtual*/ BOOL		canDeselect() const;  	/*virtual*/ void		deselect(); +	virtual void	onFocusReceived(); +	virtual void	onFocusLost(); +  	// LLSpellCheckMenuHandler overrides  	/*virtual*/ bool		getSpellCheck() const; @@ -351,6 +373,21 @@ public:  	const LLWString&       	getWText() const;  	void					appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params()); + +	void					setLabel(const LLStringExplicit& label); +	virtual BOOL			setLabelArg(const std::string& key, const LLStringExplicit& text ); + +	const	std::string& 	getLabel()	{ return mLabel.getString(); } +	const	LLWString&		getWlabel() { return mLabel.getWString();} + +	/** +	 * If label is set, draws text label (which is LLLabelTextSegment) +	 * that is visible when no user text provided and has no focus +	 */ +	void					resetLabel(); + +	void					setFont(const LLFontGL* font); +  	// force reflow of text  	void					needsReflow(S32 index = 0); @@ -390,7 +427,7 @@ public:  	bool					scrolledToStart();  	bool					scrolledToEnd(); -	const LLFontGL*			getDefaultFont() const					{ return mDefaultFont; } +	const LLFontGL*			getFont() const					{ return mFont; }  	virtual void			appendLineBreakSegment(const LLStyle::Params& style_params);  	virtual void			appendImageSegment(const LLStyle::Params& style_params); @@ -490,7 +527,7 @@ protected:  	void							createDefaultSegment();  	virtual void					updateSegments();  	void							insertSegment(LLTextSegmentPtr segment_to_insert); -	const LLStyle::Params&			getDefaultStyleParams(); +	const LLStyle::Params&			getStyleParams();  	//  manage lines  	S32								getLineStart( S32 line ) const; @@ -535,15 +572,16 @@ protected:  	LLRect						mTextBoundingRect;  	// default text style -	LLStyle::Params				mDefaultStyle; +	LLStyle::Params				mStyle;  	bool						mStyleDirty; -	const LLFontGL* const		mDefaultFont;		// font that is used when none specified, can only be set by constructor -	const LLFontGL::ShadowType	mFontShadow;		// shadow style, can only be set by constructor +	const LLFontGL*				mFont; +	const LLFontGL::ShadowType	mFontShadow;  	// colors  	LLUIColor					mCursorColor;  	LLUIColor					mFgColor;  	LLUIColor					mReadOnlyFgColor; +	LLUIColor					mTentativeFgColor;  	LLUIColor					mWriteableBgColor;  	LLUIColor					mReadOnlyBgColor;  	LLUIColor					mFocusBgColor; @@ -587,6 +625,7 @@ protected:  	bool						mClip;				// clip text to widget rect  	bool						mClipPartial;		// false if we show lines that are partially inside bounding rect  	bool						mPlainText;			// didn't use Image or Icon segments +	bool						mAutoIndent;  	S32							mMaxTextByteLength;	// Maximum length mText is allowed to be in bytes  	// support widgets @@ -602,6 +641,7 @@ protected:  	// Fired when a URL link is clicked  	commit_signal_t*			mURLClickSignal; +	LLUIString					mLabel;	// text label that is visible when no user text provided  };  #endif diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 144b6960a1..d42d6473ed 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -237,6 +237,7 @@ LLTextEditor::Params::Params()  	embedded_items("embedded_items", false),  	ignore_tab("ignore_tab", true),  	show_line_numbers("show_line_numbers", false), +	auto_indent("auto_indent", true),  	default_color("default_color"),      commit_on_focus_lost("commit_on_focus_lost", false),  	show_context_menu("show_context_menu") @@ -251,6 +252,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :  	mLastCmd( NULL ),  	mDefaultColor(		p.default_color() ),  	mShowLineNumbers ( p.show_line_numbers ), +	mAutoIndent(p.auto_indent),  	mCommitOnFocusLost( p.commit_on_focus_lost),  	mAllowEmbeddedItems( p.embedded_items ),  	mMouseDownX(0), @@ -258,7 +260,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :  	mTabsToNextField(p.ignore_tab),  	mPrevalidateFunc(p.prevalidate_callback()),  	mContextMenu(NULL), -	mShowContextMenu(p.show_context_menu) +	mShowContextMenu(p.show_context_menu), +	mPassDelete(FALSE)  {  	mSourceID.generate(); @@ -1608,7 +1611,10 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask)  			{  				deleteSelection(FALSE);  			} -			autoIndent(); // TODO: make this optional +			if (mAutoIndent) +			{ +				autoIndent(); +			}  		}  		else  		{ @@ -1748,7 +1754,7 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)  // virtual  BOOL LLTextEditor::canDoDelete() const  { -	return !mReadOnly && ( hasSelection() || (mCursorPos < getLength()) ); +	return !mReadOnly && ( !mPassDelete || ( hasSelection() || (mCursorPos < getLength())) );  }  void LLTextEditor::doDelete() @@ -2017,7 +2023,7 @@ void LLTextEditor::drawPreeditMarker()  		return;  	} -	const S32 line_height = mDefaultFont->getLineHeight(); +	const S32 line_height = mFont->getLineHeight();  	S32 line_start = getLineStart(cur_line);  	S32 line_y = mVisibleTextRect.mTop - line_height; @@ -2056,16 +2062,16 @@ void LLTextEditor::drawPreeditMarker()  				S32 preedit_left = mVisibleTextRect.mLeft;  				if (left > line_start)  				{ -					preedit_left += mDefaultFont->getWidth(text, line_start, left - line_start); +					preedit_left += mFont->getWidth(text, line_start, left - line_start);  				}  				S32 preedit_right = mVisibleTextRect.mLeft;  				if (right < line_end)  				{ -					preedit_right += mDefaultFont->getWidth(text, line_start, right - line_start); +					preedit_right += mFont->getWidth(text, line_start, right - line_start);  				}  				else  				{ -					preedit_right += mDefaultFont->getWidth(text, line_start, line_end - line_start); +					preedit_right += mFont->getWidth(text, line_start, line_end - line_start);  				}  				if (mPreeditStandouts[i]) @@ -2740,11 +2746,11 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect      const LLWString textString(getWText());  	const llwchar * const text = textString.c_str(); -	const S32 line_height = mDefaultFont->getLineHeight(); +	const S32 line_height = mFont->getLineHeight();  	if (coord)  	{ -		const S32 query_x = mVisibleTextRect.mLeft + mDefaultFont->getWidth(text, current_line_start, query - current_line_start); +		const S32 query_x = mVisibleTextRect.mLeft + mFont->getWidth(text, current_line_start, query - current_line_start);  		const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;  		S32 query_screen_x, query_screen_y;  		localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y); @@ -2756,17 +2762,17 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect  		S32 preedit_left = mVisibleTextRect.mLeft;  		if (preedit_left_position > current_line_start)  		{ -			preedit_left += mDefaultFont->getWidth(text, current_line_start, preedit_left_position - current_line_start); +			preedit_left += mFont->getWidth(text, current_line_start, preedit_left_position - current_line_start);  		}  		S32 preedit_right = mVisibleTextRect.mLeft;  		if (preedit_right_position < current_line_end)  		{ -			preedit_right += mDefaultFont->getWidth(text, current_line_start, preedit_right_position - current_line_start); +			preedit_right += mFont->getWidth(text, current_line_start, preedit_right_position - current_line_start);  		}  		else  		{ -			preedit_right += mDefaultFont->getWidth(text, current_line_start, current_line_end - current_line_start); +			preedit_right += mFont->getWidth(text, current_line_start, current_line_end - current_line_start);  		}  		const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height; @@ -2843,7 +2849,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length)  S32 LLTextEditor::getPreeditFontSize() const  { -	return llround((F32)mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); +	return llround((F32)mFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);  }  BOOL LLTextEditor::isDirty() const diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 40821ae9fb..f8f636b876 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -64,7 +64,8 @@ public:  								ignore_tab,  								show_line_numbers,  								commit_on_focus_lost, -								show_context_menu; +								show_context_menu, +								auto_indent;  		//colors  		Optional<LLUIColor>		default_color; @@ -202,6 +203,8 @@ public:  	void			setShowContextMenu(bool show) { mShowContextMenu = show; }  	bool			getShowContextMenu() const { return mShowContextMenu; } +	void			setPassDelete(BOOL b) { mPassDelete = b; } +  protected:  	void			showContextMenu(S32 x, S32 y);  	void			drawPreeditMarker(); @@ -214,8 +217,8 @@ protected:  	S32				indentLine( S32 pos, S32 spaces );  	void			unindentLineBeforeCloseBrace(); +	virtual	BOOL	handleSpecialKey(const KEY key, const MASK mask);  	BOOL			handleNavigationKey(const KEY key, const MASK mask); -	BOOL			handleSpecialKey(const KEY key, const MASK mask);  	BOOL			handleSelectionKey(const KEY key, const MASK mask);  	BOOL			handleControlKey(const KEY key, const MASK mask); @@ -279,6 +282,7 @@ protected:  	LLUIColor			mDefaultColor;  	BOOL				mShowLineNumbers; +	bool				mAutoIndent;  	/*virtual*/ void	updateSegments();  	void				updateLinkSegments(); @@ -321,6 +325,7 @@ private:  	BOOL			mAllowEmbeddedItems;  	bool			mShowContextMenu;  	bool			mParseOnTheFly; +	bool			mPassDelete;  	LLUUID			mSourceID; diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h index 2094bd776f..dd9ac5b8c1 100644 --- a/indra/llui/lltoggleablemenu.h +++ b/indra/llui/lltoggleablemenu.h @@ -58,6 +58,8 @@ public:  	// its visibility off.  	bool toggleVisibility(); +	LLHandle<LLToggleableMenu> getHandle() { return getDerivedHandle<LLToggleableMenu>(); } +  protected:  	bool mClosedByButtonClick;  	LLRect mButtonRect; diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index f737d48abf..d4670efedf 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -288,7 +288,7 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)  		mTextBox->setText(p.message());  	} -	S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth()); +	S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth() + 1);  	S32 text_height = mTextBox->getTextPixelHeight();  	mTextBox->reshape(text_width, text_height);  	if (mInfoButton) diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 87bf518aa1..41a948e545 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -978,31 +978,31 @@ void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)  {  	if (!LLGLSLShader::sNoFixedFunction)  	{  -		// Initialize the first time this is called. -		const S32 PIXELS = 32; -		static GLubyte checkerboard[PIXELS * PIXELS]; -		static BOOL first = TRUE; -		if( first ) +	// Initialize the first time this is called. +	const S32 PIXELS = 32; +	static GLubyte checkerboard[PIXELS * PIXELS]; +	static BOOL first = TRUE; +	if( first ) +	{ +		for( S32 i = 0; i < PIXELS; i++ )  		{ -			for( S32 i = 0; i < PIXELS; i++ ) +			for( S32 j = 0; j < PIXELS; j++ )  			{ -				for( S32 j = 0; j < PIXELS; j++ ) -				{ -					checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; -				} +				checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF;  			} -			first = FALSE;  		} +		first = FALSE; +	} -		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -		// ...white squares -		gGL.color4f( 1.f, 1.f, 1.f, alpha ); -		gl_rect_2d(rect); +	// ...white squares +	gGL.color4f( 1.f, 1.f, 1.f, alpha ); +	gl_rect_2d(rect); -		// ...gray squares -		gGL.color4f( .7f, .7f, .7f, alpha ); -		gGL.flush(); +	// ...gray squares +	gGL.color4f( .7f, .7f, .7f, alpha ); +	gGL.flush();  		glPolygonStipple( checkerboard ); @@ -1478,144 +1478,132 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left,  	gGL.popUIMatrix();  } -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width,  -							  const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, -							  const U32 edges) +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect,  +							 const LLVector3& width_vec, const LLVector3& height_vec)  { -	LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero; -	LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero; - -	LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero; -	LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero; - -  	gGL.begin(LLRender::QUADS);  	{  		// draw bottom left -		gGL.texCoord2f(0.f, 0.f); +		gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom);  		gGL.vertex3f(0.f, 0.f, 0.f); -		gGL.texCoord2f(border_scale.mV[VX], 0.f); -		gGL.vertex3fv(left_border_width.mV); +		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(0.f, border_scale.mV[VY]); -		gGL.vertex3fv(bottom_border_height.mV); +		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);  		// draw bottom middle -		gGL.texCoord2f(border_scale.mV[VX], 0.f); -		gGL.vertex3fv(left_border_width.mV); +		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); -		gGL.vertex3fv((width_vec - right_border_width).mV); +		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);  		// draw bottom right -		gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); -		gGL.vertex3fv((width_vec - right_border_width).mV); +		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); -		gGL.texCoord2f(1.f, 0.f); +		gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom);  		gGL.vertex3fv(width_vec.mV); -		gGL.texCoord2f(1.f, border_scale.mV[VY]); -		gGL.vertex3fv((width_vec + bottom_border_height).mV); +		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);  		// draw left  -		gGL.texCoord2f(0.f, border_scale.mV[VY]); -		gGL.vertex3fv(bottom_border_height.mV); +		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((height_vec - top_border_height).mV); +		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);  		// draw middle -		gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);  		// draw right  -		gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f, border_scale.mV[VY]); -		gGL.vertex3fv((width_vec + bottom_border_height).mV); +		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); +		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);  		// draw top left -		gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((height_vec - top_border_height).mV); +		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f); -		gGL.vertex3fv((left_border_width + height_vec).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); -		gGL.texCoord2f(0.f, 1.f); +		gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop);  		gGL.vertex3fv((height_vec).mV);  		// draw top middle -		gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); -		gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); +		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f); -		gGL.vertex3fv((left_border_width + height_vec).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);  		// draw top right -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); +		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f, 1.f); +		gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop);  		gGL.vertex3fv((width_vec + height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); -		gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); +		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);  	}  	gGL.end();  } -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec) -{ -	gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP); -}  void LLUI::initClass(const settings_map_t& settings,  					 LLImageProviderInterface* image_provider, @@ -2118,7 +2106,7 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)  namespace LLInitParam  { -	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) +	ParamValue<LLUIColor>::ParamValue(const LLUIColor& color)  	:	super_t(color),  		red("red"),  		green("green"), @@ -2129,7 +2117,7 @@ namespace LLInitParam  		updateBlockFromValue(false);  	} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() +	void ParamValue<LLUIColor>::updateValueFromBlock()  	{  		if (control.isProvided() && !control().empty())  		{ @@ -2141,7 +2129,7 @@ namespace LLInitParam  		}  	} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<LLUIColor>::updateBlockFromValue(bool make_block_authoritative)  	{  		LLColor4 color = getValue();  		red.set(color.mV[VRED], make_block_authoritative); @@ -2157,7 +2145,7 @@ namespace LLInitParam  			&& !(b->getFontDesc() < a->getFontDesc());  	} -	ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) +	ParamValue<const LLFontGL*>::ParamValue(const LLFontGL* fontp)  	:	super_t(fontp),  		name("name"),  		size("size"), @@ -2171,7 +2159,7 @@ namespace LLInitParam  		updateBlockFromValue(false);  	} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() +	void ParamValue<const LLFontGL*>::updateValueFromBlock()  	{  		const LLFontGL* res_fontp = LLFontGL::getFontByName(name);  		if (res_fontp) @@ -2194,7 +2182,7 @@ namespace LLInitParam  		}  	} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<const LLFontGL*>::updateBlockFromValue(bool make_block_authoritative)  	{  		if (getValue())  		{ @@ -2204,7 +2192,7 @@ namespace LLInitParam  		}  	} -	ParamValue<LLRect, TypeValues<LLRect> >::ParamValue(const LLRect& rect) +	ParamValue<LLRect>::ParamValue(const LLRect& rect)  	:	super_t(rect),  		left("left"),  		top("top"), @@ -2216,7 +2204,7 @@ namespace LLInitParam  		updateBlockFromValue(false);  	} -	void ParamValue<LLRect, TypeValues<LLRect> >::updateValueFromBlock() +	void ParamValue<LLRect>::updateValueFromBlock()  	{  		LLRect rect; @@ -2280,7 +2268,7 @@ namespace LLInitParam  		updateValue(rect);  	} -	void ParamValue<LLRect, TypeValues<LLRect> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<LLRect>::updateBlockFromValue(bool make_block_authoritative)  	{  		// because of the ambiguity in specifying a rect by position and/or dimensions  		// we use the lowest priority pairing so that any valid pairing in xui  @@ -2297,7 +2285,7 @@ namespace LLInitParam  		height.set(value.getHeight(), make_block_authoritative);  	} -	ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::ParamValue(const LLCoordGL& coord) +	ParamValue<LLCoordGL>::ParamValue(const LLCoordGL& coord)  	:	super_t(coord),  		x("x"),  		y("y") @@ -2305,12 +2293,12 @@ namespace LLInitParam  		updateBlockFromValue(false);  	} -	void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateValueFromBlock() +	void ParamValue<LLCoordGL>::updateValueFromBlock()  	{  		updateValue(LLCoordGL(x, y));  	} -	void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<LLCoordGL>::updateBlockFromValue(bool make_block_authoritative)  	{  		x.set(getValue().mX, make_block_authoritative);  		y.set(getValue().mY, make_block_authoritative); diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 28e84fa444..1fbfbd7a07 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -127,8 +127,7 @@ typedef enum e_rounded_edge  void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL);  void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec); +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec);  inline void gl_rect_2d( const LLRect& rect, BOOL filled )  { @@ -512,7 +511,7 @@ public:  namespace LLInitParam  {  	template<> -	class ParamValue<LLRect, TypeValues<LLRect> >  +	class ParamValue<LLRect>   	:	public CustomParamValue<LLRect>  	{          typedef CustomParamValue<LLRect> super_t; @@ -531,7 +530,7 @@ namespace LLInitParam  	};  	template<> -	class ParamValue<LLUIColor, TypeValues<LLUIColor> >  +	class ParamValue<LLUIColor>   	:	public CustomParamValue<LLUIColor>  	{          typedef CustomParamValue<LLUIColor> super_t; @@ -549,7 +548,7 @@ namespace LLInitParam  	};  	template<> -	class ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >  +	class ParamValue<const LLFontGL*>   	:	public CustomParamValue<const LLFontGL* >  	{          typedef CustomParamValue<const LLFontGL*> super_t; @@ -589,7 +588,7 @@ namespace LLInitParam  	template<> -	class ParamValue<LLCoordGL, TypeValues<LLCoordGL> > +	class ParamValue<LLCoordGL>  	:	public CustomParamValue<LLCoordGL>  	{  		typedef CustomParamValue<LLCoordGL> super_t; diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 25e7a31e90..91a6b3259c 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -278,13 +278,13 @@ const LLInitParam::BaseBlock& get_empty_param_block()  // adds a widget and its param block to various registries  //static  -void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag) +void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& name)  {  	// associate parameter block type with template .xml file -	std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type); -	if (existing_tag != NULL) +	std::string* existing_name = LLWidgetNameRegistry::instance().getValue(param_block_type); +	if (existing_name != NULL)  	{ -		if(*existing_tag != tag) +		if(*existing_name != name)  		{  			std::cerr << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << std::endl;  			// forcing crash here @@ -293,19 +293,15 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st  		}  		else  		{ -			// widget already registered +			// widget already registered this name  			return;  		}  	} -	LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, tag); + +	LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, name);  	//FIXME: comment this in when working on schema generation  	//LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type);  	//LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &get_empty_param_block<T>);  } -//static  -const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type) -{ -	return LLWidgetNameRegistry::instance().getValue(widget_type); -} diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index d612ad5005..4ce1aeac76 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -31,18 +31,10 @@  #include "llinitparam.h"  #include "llregistry.h"  #include "llxuiparser.h" +#include "llstl.h"  class LLView; -// sort functor for typeid maps -struct LLCompareTypeID -{ -	bool operator()(const std::type_info* lhs, const std::type_info* rhs) const -	{ -		return lhs->before(*rhs); -	} -}; -  // lookup widget constructor funcs by widget name  template <typename DERIVED_TYPE>  class LLChildRegistry : public LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE> @@ -71,14 +63,14 @@ protected:  // lookup widget name by type  class LLWidgetNameRegistry  -:	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry , LLCompareTypeID> +:	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry>  {};  // lookup function for generating empty param block by widget type  // this is used for schema generation  //typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();  //class LLDefaultParamBlockRegistry -//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID> +//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry>  //{};  extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP; @@ -105,7 +97,7 @@ private:  		ParamDefaults()  		{  			// look up template file for this param block... -			const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK)); +			const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK));  			if (param_block_tag)  			{	// ...and if it exists, back fill values using the most specific template first  				PARAM_BLOCK params; @@ -139,7 +131,6 @@ public:  	template<typename T>  	static const typename T::Params& getDefaultParams()  	{ -		//#pragma message("Generating ParamDefaults")  		return ParamDefaults<typename T::Params, 0>::instance().get();  	} @@ -303,8 +294,6 @@ private:  	} -	static const std::string* getWidgetTag(const std::type_info* widget_type); -  	// this exists to get around dependency on llview  	static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index 1d9ce29ba9..9ed98f941f 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -112,6 +112,50 @@ void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4&  	drawSolid(border_rect, color);  } +void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis,  +						const LLRect& rect, const LLColor4& color) +{ +	F32 border_scale = 1.f; +	F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight(); +	F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth(); +	if (rect.getHeight() < border_height || rect.getWidth() < border_width) +	{ +		 if(border_height - rect.getHeight() > border_width - rect.getWidth()) +		 { +			 border_scale = (F32)rect.getHeight() / border_height; +		 } +		 else +		 { +			border_scale = (F32)rect.getWidth() / border_width; +		 } +	} + +	LLUI::pushMatrix(); +	{  +		LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis);  +		LLUI::translate(rect_origin.mV[VX], +						rect_origin.mV[VY],  +						rect_origin.mV[VZ]); +		gGL.getTexUnit(0)->bind(getImage()); +		gGL.color4fv(color.mV); + +		LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(), +							mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(), +							mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(), +							mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight()); +		gl_segmented_rect_3d_tex(mClipRegion, +								center_uv_rect, +								LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(), +										(rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(), +										(rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(), +										(border_height * border_scale * 0.5f) / (F32)rect.getHeight()), +								rect.getWidth() * x_axis,  +								rect.getHeight() * y_axis); +		 +	} LLUI::popMatrix(); +} + +  S32 LLUIImage::getWidth() const  {   	// return clipped dimensions of actual image area @@ -155,7 +199,7 @@ void LLUIImage::onImageLoaded()  namespace LLInitParam  { -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() +	void ParamValue<LLUIImage*>::updateValueFromBlock()  	{  		// The keyword "none" is specifically requesting a null image  		// do not default to current value. Used to overwrite template images.  @@ -172,7 +216,7 @@ namespace LLInitParam  		}  	} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<LLUIImage*>::updateBlockFromValue(bool make_block_authoritative)  	{  		if (getValue() == NULL)  		{ diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h index f07e8fa746..7817ba1c7b 100644 --- a/indra/llui/lluiimage.h +++ b/indra/llui/lluiimage.h @@ -64,7 +64,9 @@ public:  	void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;  	void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }  	void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); } -	 + +	void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color); +  	const std::string& getName() const { return mName; }  	virtual S32 getWidth() const; @@ -92,7 +94,7 @@ protected:  namespace LLInitParam  {  	template<> -	class ParamValue<LLUIImage*, TypeValues<LLUIImage*> >  +	class ParamValue<LLUIImage*>   	:	public CustomParamValue<LLUIImage*>  	{  		typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type	T_const_ref; @@ -100,7 +102,7 @@ namespace LLInitParam  	public:  		Optional<std::string> name; -		ParamValue(LLUIImage* const& image) +		ParamValue(LLUIImage* const& image = NULL)  		:	super_t(image)  		{  			updateBlockFromValue(false); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 54843227b7..5c2b3236f6 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -349,7 +349,7 @@ void LLView::removeChild(LLView* child)  	}  	else  	{ -		llwarns << child->getName() << "is not a child of " << getName() << llendl; +		llwarns << "\"" << child->getName() << "\" is not a child of " << getName() << llendl;  	}  	updateBoundingRect();  } diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp index afc76024d1..3ad5ad7d42 100644 --- a/indra/llui/llxuiparser.cpp +++ b/indra/llui/llxuiparser.cpp @@ -42,7 +42,7 @@  #include <boost/spirit/include/classic_core.hpp>  #include "lluicolor.h" - +#include "v3math.h"  using namespace BOOST_SPIRIT_CLASSIC_NS;  const S32 MAX_STRING_ATTRIBUTE_SIZE = 40; @@ -79,7 +79,6 @@ struct Occurs : public LLInitParam::Block<Occurs>  	{}  }; -  typedef enum  {  	USE_REQUIRED, @@ -101,14 +100,23 @@ namespace LLInitParam  struct Element;  struct Group; -struct Choice;  struct Sequence; -struct Any; + +struct All : public LLInitParam::Block<All, Occurs> +{ +	Multiple< Lazy<Element, IS_A_BLOCK> > elements; + +	All() +	:	elements("element") +	{ +		maxOccurs = 1; +	} +};  struct Attribute : public LLInitParam::Block<Attribute>  { -	Mandatory<std::string>	name; -	Mandatory<std::string>	type; +	Mandatory<std::string>	name, +							type;  	Mandatory<EUse>			use;  	Attribute() @@ -127,24 +135,13 @@ struct Any : public LLInitParam::Block<Any, Occurs>  	{}  }; -struct All : public LLInitParam::Block<All, Occurs> -{ -	Multiple< Lazy<Element> > elements; - -	All() -	:	elements("element") -	{ -		maxOccurs = 1; -	} -}; -  struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs>  { -	Alternative< Lazy<Element> >	element; -	Alternative< Lazy<Group> >		group; -	Alternative< Lazy<Choice> >		choice; -	Alternative< Lazy<Sequence> >	sequence; -	Alternative< Lazy<Any> >		any; +	Alternative< Lazy<Element, IS_A_BLOCK> >	element; +	Alternative< Lazy<Group, IS_A_BLOCK> >		group; +	Alternative< Lazy<Choice, IS_A_BLOCK> >		choice; +	Alternative< Lazy<Sequence, IS_A_BLOCK> >	sequence; +	Alternative< Lazy<Any> >					any;  	Choice()  	:	element("element"), @@ -158,11 +155,11 @@ struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs>  struct Sequence : public LLInitParam::ChoiceBlock<Sequence, Occurs>  { -	Alternative< Lazy<Element> >	element; -	Alternative< Lazy<Group> >		group; -	Alternative< Lazy<Choice> >		choice; -	Alternative< Lazy<Sequence> >	sequence; -	Alternative< Lazy<Any> >		any; +	Alternative< Lazy<Element, IS_A_BLOCK> >	element; +	Alternative< Lazy<Group, IS_A_BLOCK> >		group; +	Alternative< Lazy<Choice> >					choice; +	Alternative< Lazy<Sequence, IS_A_BLOCK> >	sequence; +	Alternative< Lazy<Any> >					any;  };  struct GroupContents : public LLInitParam::ChoiceBlock<GroupContents, Occurs> @@ -247,7 +244,7 @@ struct ComplexType : public LLInitParam::Block<ComplexType, ComplexTypeContents>  	Optional<bool>					mixed;  	Multiple<Attribute>				attribute; -	Multiple< Lazy<Element> >			elements; +	Multiple< Lazy<Element, IS_A_BLOCK > >			elements;  	ComplexType()  	:	name("name"), @@ -313,7 +310,6 @@ public:  			setNameSpace(ns);  		};  	} -  };  // @@ -625,7 +621,7 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p  			nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd");  			// add to front of schema -			mSchemaNode->addChild(nodep, mSchemaNode); +			mSchemaNode->addChild(nodep);  		}  		for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); @@ -670,6 +666,7 @@ LLXUIParser::LLXUIParser()  		registerParserFuncs<S32>(readS32Value, writeS32Value);  		registerParserFuncs<F32>(readF32Value, writeF32Value);  		registerParserFuncs<F64>(readF64Value, writeF64Value); +		registerParserFuncs<LLVector3>(readVector3Value, writeVector3Value);  		registerParserFuncs<LLColor4>(readColor4Value, writeColor4Value);  		registerParserFuncs<LLUIColor>(readUIColorValue, writeUIColorValue);  		registerParserFuncs<LLUUID>(readUUIDValue, writeUUIDValue); @@ -880,16 +877,24 @@ LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack)  		it = next_it)  	{  		++next_it; +		bool force_new_node = false; +  		if (it->first.empty())  		{  			it->second = false;  			continue;  		} +		if (next_it != stack.end() && next_it->first.empty() && next_it->second) +		{ +			force_new_node = true; +		} + +  		out_nodes_t::iterator found_it = mOutNodes.find(it->first);  		// node with this name not yet written -		if (found_it == mOutNodes.end() || it->second) +		if (found_it == mOutNodes.end() || it->second || force_new_node)  		{  			// make an attribute if we are the last element on the name stack  			bool is_attribute = next_it == stack.end(); @@ -1144,6 +1149,31 @@ bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_  	return false;  } +bool LLXUIParser::readVector3Value(Parser& parser, void* val_ptr) +{ +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	LLVector3* vecp = (LLVector3*)val_ptr; +	if(self.mCurReadNode->getFloatValue(3, vecp->mV) >= 3) +	{ +		return true; +	} + +	return false; +} + +bool LLXUIParser::writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	LLXMLNodePtr node = self.getNode(stack); +	if (node.notNull()) +	{ +		LLVector3 vector = *((LLVector3*)val_ptr); +		node->setFloatValue(3, vector.mV); +		return true; +	} +	return false; +} +  bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)  {  	LLXUIParser& self = static_cast<LLXUIParser&>(parser); diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h index d7cd256967..e48663e5cc 100644 --- a/indra/llui/llxuiparser.h +++ b/indra/llui/llxuiparser.h @@ -127,6 +127,7 @@ private:  	static bool readS32Value(Parser& parser, void* val_ptr);  	static bool readF32Value(Parser& parser, void* val_ptr);  	static bool readF64Value(Parser& parser, void* val_ptr); +	static bool readVector3Value(Parser& parser, void* val_ptr);  	static bool readColor4Value(Parser& parser, void* val_ptr);  	static bool readUIColorValue(Parser& parser, void* val_ptr);  	static bool readUUIDValue(Parser& parser, void* val_ptr); @@ -144,6 +145,7 @@ private:  	static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&); +	static bool writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&); diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index 74ed72ef97..f8797fd257 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -106,14 +106,14 @@ LLStyle::Params::Params()  namespace LLInitParam  { -	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) +	ParamValue<LLUIColor>::ParamValue(const LLUIColor& color)  	:	super_t(color)  	{} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock()  +	void ParamValue<LLUIColor>::updateValueFromBlock()   	{} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue(bool) +	void ParamValue<LLUIColor>::updateBlockFromValue(bool)  	{}  	bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -121,14 +121,14 @@ namespace LLInitParam  		return false;  	} -	ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) +	ParamValue<const LLFontGL*>::ParamValue(const LLFontGL* fontp)  	:	super_t(fontp)  	{} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() +	void ParamValue<const LLFontGL*>::updateValueFromBlock()  	{} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue(bool) +	void ParamValue<const LLFontGL*>::updateBlockFromValue(bool)  	{}  	void TypeValues<LLFontGL::HAlign>::declareValues() @@ -140,10 +140,10 @@ namespace LLInitParam  	void TypeValues<LLFontGL::ShadowType>::declareValues()  	{} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() +	void ParamValue<LLUIImage*>::updateValueFromBlock()  	{} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool) +	void ParamValue<LLUIImage*>::updateBlockFromValue(bool)  	{} diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 963473c92a..109d3ca7bb 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -63,14 +63,14 @@ S32 LLUIImage::getHeight() const  namespace LLInitParam  { -	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) +	ParamValue<LLUIColor>::ParamValue(const LLUIColor& color)  	:	super_t(color)  	{} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() +	void ParamValue<LLUIColor>::updateValueFromBlock()  	{} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue(bool) +	void ParamValue<LLUIColor>::updateBlockFromValue(bool)  	{}  	bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -79,14 +79,14 @@ namespace LLInitParam  	} -	ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) +	ParamValue<const LLFontGL*>::ParamValue(const LLFontGL* fontp)  	:	super_t(fontp)  	{} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() +	void ParamValue<const LLFontGL*>::updateValueFromBlock()  	{} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue(bool) +	void ParamValue<const LLFontGL*>::updateBlockFromValue(bool)  	{}  	void TypeValues<LLFontGL::HAlign>::declareValues() @@ -98,10 +98,10 @@ namespace LLInitParam  	void TypeValues<LLFontGL::ShadowType>::declareValues()  	{} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() +	void ParamValue<LLUIImage*>::updateValueFromBlock()  	{} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool) +	void ParamValue<LLUIImage*>::updateBlockFromValue(bool)  	{}  	bool ParamCompare<LLUIImage*, false>::equals( diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 2ffb0d8503..afb0d87da9 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -147,13 +147,15 @@ LLXMLNodePtr LLXMLNode::deepCopy()  		for (LLXMLChildList::iterator iter = mChildren->map.begin();  			 iter != mChildren->map.end(); ++iter)	  		{ -			newnode->addChild(iter->second->deepCopy()); +			LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); +			newnode->addChild(temp_ptr_for_gcc);  		}  	}  	for (LLXMLAttribList::iterator iter = mAttributes.begin();  		 iter != mAttributes.end(); ++iter)  	{ -		newnode->addChild(iter->second->deepCopy()); +		LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); +		newnode->addChild(temp_ptr_for_gcc);  	}  	return newnode; @@ -259,7 +261,7 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child)  	return FALSE;  } -void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) +void LLXMLNode::addChild(LLXMLNodePtr& new_child)  {  	if (new_child->mParent != NULL)  	{ @@ -273,6 +275,11 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child)  	new_child->mParent = this;  	if (new_child->mIsAttribute)  	{ +		LLXMLAttribList::iterator found_it = mAttributes.find(new_child->mName); +		if (found_it != mAttributes.end()) +		{ +			removeChild(found_it->second); +		}  		mAttributes.insert(std::make_pair(new_child->mName, new_child));  	}  	else @@ -285,49 +292,11 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child)  		}  		mChildren->map.insert(std::make_pair(new_child->mName, new_child)); -		// if after_child is specified, it damn well better be in the list of children -		// for this node. I'm not going to assert that, because it would be expensive, -		// but don't specify that parameter if you didn't get the value for it from the -		// list of children of this node! -		if (after_child.isNull()) -		{ -			if (mChildren->tail != new_child) -			{ -				mChildren->tail->mNext = new_child; -				new_child->mPrev = mChildren->tail; -				mChildren->tail = new_child; -			} -		} -		// if after_child == parent, then put new_child at beginning -		else if (after_child == this) -		{ -			// add to front of list -			new_child->mNext = mChildren->head; -			if (mChildren->head) -			{ -				mChildren->head->mPrev = new_child; -				mChildren->head = new_child; -			} -			else // no children -			{ -				mChildren->head = new_child; -				mChildren->tail = new_child; -			} -		} -		else +		if (mChildren->tail != new_child)  		{ -			if (after_child->mNext.notNull()) -			{ -				// if after_child was not the last item, fix up some pointers -				after_child->mNext->mPrev = new_child; -				new_child->mNext = after_child->mNext; -			} -			new_child->mPrev = after_child; -			after_child->mNext = new_child; -			if (mChildren->tail == after_child) -			{ -				mChildren->tail = new_child; -			} +			mChildren->tail->mNext = new_child; +			new_child->mPrev = mChildren->tail; +			mChildren->tail = new_child;  		}  	} @@ -343,8 +312,9 @@ LLXMLNodePtr LLXMLNode::createChild(const char* name, BOOL is_attribute)  // virtual   LLXMLNodePtr LLXMLNode::createChild(LLStringTableEntry* name, BOOL is_attribute)  { -	LLXMLNode* ret = new LLXMLNode(name, is_attribute); +	LLXMLNodePtr ret(new LLXMLNode(name, is_attribute));  	ret->mID.clear(); +	  	addChild(ret);  	return ret;  } @@ -358,11 +328,12 @@ BOOL LLXMLNode::deleteChild(LLXMLNode *child)  	return FALSE;  } -void LLXMLNode::setParent(LLXMLNodePtr new_parent) +void LLXMLNode::setParent(LLXMLNodePtr& new_parent)  {  	if (new_parent.notNull())  	{ -		new_parent->addChild(this); +		LLXMLNodePtr this_ptr(this); +		new_parent->addChild(this_ptr);  	}  	else  	{ @@ -681,27 +652,6 @@ bool LLXMLNode::updateNode(  	return TRUE;  } - -// static  -LLXMLNodePtr LLXMLNode::replaceNode(LLXMLNodePtr node, LLXMLNodePtr update_node) -{	 -	if (!node || !update_node) -	{ -		llwarns << "Node invalid" << llendl; -		return node; -	} -	 -	LLXMLNodePtr cloned_node = update_node->deepCopy(); -	node->mParent->addChild(cloned_node, node);	// add after node -	LLXMLNodePtr parent = node->mParent; -	parent->removeChild(node); -	parent->updateDefault(); -	 -	return cloned_node; -} - - -  // static  bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXMLNode* defaults_tree)  { @@ -1198,7 +1148,8 @@ void LLXMLNode::scrubToTree(LLXMLNode *tree)  		std::vector<LLXMLNodePtr>::iterator itor3;  		for (itor3=to_delete_list.begin(); itor3!=to_delete_list.end(); ++itor3)  		{ -			(*itor3)->setParent(NULL); +			LLXMLNodePtr ptr; +			(*itor3)->setParent(ptr);  		}  	}  } @@ -2733,7 +2684,8 @@ void LLXMLNode::setName(LLStringTableEntry* name)  	mName = name;  	if (old_parent)  	{ -		old_parent->addChild(this); +		LLXMLNodePtr this_ptr(this); +		old_parent->addChild(this_ptr);  	}  } diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index e3da7169e7..ec486d7957 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -127,8 +127,8 @@ public:  	BOOL isNull();  	BOOL deleteChild(LLXMLNode* child); -    void addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child = LLXMLNodePtr(NULL));  -    void setParent(LLXMLNodePtr new_parent); // reparent if necessary +    void addChild(LLXMLNodePtr& new_child);  +    void setParent(LLXMLNodePtr& new_parent); // reparent if necessary      // Serialization  	static bool parseFile( @@ -147,7 +147,6 @@ public:  	static bool updateNode(  		LLXMLNodePtr& node,  		LLXMLNodePtr& update_node); -	static LLXMLNodePtr replaceNode(LLXMLNodePtr node, LLXMLNodePtr replacement_node);  	static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector<std::string>& paths); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3cd03f8641..b94c33587b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -110,6 +110,8 @@ set(viewer_SOURCE_FILES      llavatarlist.cpp      llavatarlistitem.cpp      llavatarpropertiesprocessor.cpp +    llblockedlistitem.cpp +    llblocklist.cpp      llbox.cpp      llbreadcrumbview.cpp      llbrowsernotification.cpp @@ -135,6 +137,11 @@ set(viewer_SOURCE_FILES      llcommandlineparser.cpp      llcompilequeue.cpp      llconfirmationmanager.cpp +    llconversationlog.cpp +    llconversationloglist.cpp +    llconversationloglistitem.cpp +    llconversationmodel.cpp +    llconversationview.cpp      llcurrencyuimanager.cpp      llcylinder.cpp      lldateutil.cpp @@ -191,6 +198,8 @@ set(viewer_SOURCE_FILES      llfloaterbuyland.cpp      llfloatercamera.cpp      llfloatercolorpicker.cpp +    llfloaterconversationlog.cpp +    llfloaterconversationpreview.cpp      llfloaterdeleteenvpreset.cpp      llfloaterdestinations.cpp      llfloaterdisplayname.cpp @@ -258,13 +267,13 @@ set(viewer_SOURCE_FILES      llfloateruipreview.cpp      llfloaterurlentry.cpp      llfloatervoiceeffect.cpp +    llfloatervoicevolume.cpp      llfloaterwebcontent.cpp      llfloaterwebprofile.cpp      llfloaterwhitelistentry.cpp      llfloaterwindowsize.cpp      llfloaterworldmap.cpp -    llfolderview.cpp -    llfolderviewitem.cpp +    llfolderviewmodelinventory.cpp      llfollowcam.cpp      llfriendcard.cpp      llgesturelistener.cpp @@ -290,6 +299,7 @@ set(viewer_SOURCE_FILES      llhudrender.cpp      llhudtext.cpp      llhudview.cpp +    llimconversation.cpp      llimfloater.cpp      llimfloatercontainer.cpp      llimhandler.cpp @@ -344,7 +354,6 @@ set(viewer_SOURCE_FILES      llnamelistctrl.cpp      llnavigationbar.cpp      llnearbychat.cpp -    llnearbychatbar.cpp      llnearbychathandler.cpp      llnearbychatbarlistener.cpp      llnetmap.cpp @@ -376,7 +385,6 @@ set(viewer_SOURCE_FILES      llpanelgroupnotices.cpp      llpanelgrouproles.cpp      llpanelhome.cpp -    llpanelimcontrolpanel.cpp      llpanelland.cpp      llpanellandaudio.cpp      llpanellandmarkinfo.cpp @@ -387,7 +395,6 @@ set(viewer_SOURCE_FILES      llpanelmaininventory.cpp      llpanelmarketplaceinbox.cpp      llpanelmarketplaceinboxinventory.cpp -    llpanelmarketplaceoutboxinventory.cpp      llpanelmediasettingsgeneral.cpp      llpanelmediasettingspermissions.cpp      llpanelmediasettingssecurity.cpp @@ -442,6 +449,7 @@ set(viewer_SOURCE_FILES      llphysicsshapebuilderutil.cpp      llplacesinventorybridge.cpp      llplacesinventorypanel.cpp +    llplacesfolderview.cpp      llpopupview.cpp      llpolymesh.cpp      llpolymorph.cpp @@ -686,6 +694,8 @@ set(viewer_HEADER_FILES      llavatarlist.h      llavatarlistitem.h      llavatarpropertiesprocessor.h +    llblockedlistitem.h +    llblocklist.h      llbox.h      llbreadcrumbview.h      llbuycurrencyhtml.h @@ -711,6 +721,11 @@ set(viewer_HEADER_FILES      llcommandlineparser.h      llcompilequeue.h      llconfirmationmanager.h +    llconversationlog.h +    llconversationloglist.h +    llconversationloglistitem.h +    llconversationmodel.h +    llconversationview.h      llcurrencyuimanager.h      llcylinder.h      lldateutil.h @@ -767,6 +782,8 @@ set(viewer_HEADER_FILES      llfloaterbuyland.h      llfloatercamera.h      llfloatercolorpicker.h +    llfloaterconversationlog.h +    llfloaterconversationpreview.h      llfloaterdeleteenvpreset.h      llfloaterdestinations.h      llfloaterdisplayname.h @@ -834,14 +851,13 @@ set(viewer_HEADER_FILES      llfloateruipreview.h      llfloaterurlentry.h      llfloatervoiceeffect.h +    llfloatervoicevolume.h      llfloaterwebcontent.h      llfloaterwebprofile.h      llfloaterwhitelistentry.h      llfloaterwindowsize.h      llfloaterworldmap.h -    llfolderview.h -    llfoldervieweventlistener.h -    llfolderviewitem.h +    llfolderviewmodelinventory.h      llfollowcam.h      llfriendcard.h      llgesturelistener.h @@ -866,6 +882,7 @@ set(viewer_HEADER_FILES      llhudrender.h      llhudtext.h      llhudview.h +    llimconversation.h      llimfloater.h      llimfloatercontainer.h      llimview.h @@ -920,7 +937,6 @@ set(viewer_HEADER_FILES      llnamelistctrl.h      llnavigationbar.h      llnearbychat.h -    llnearbychatbar.h      llnearbychathandler.h      llnearbychatbarlistener.h      llnetmap.h @@ -946,7 +962,6 @@ set(viewer_HEADER_FILES      llpanelgroupnotices.h      llpanelgrouproles.h      llpanelhome.h -    llpanelimcontrolpanel.h      llpanelland.h      llpanellandaudio.h      llpanellandmarkinfo.h @@ -957,7 +972,6 @@ set(viewer_HEADER_FILES      llpanelmaininventory.h      llpanelmarketplaceinbox.h      llpanelmarketplaceinboxinventory.h -    llpanelmarketplaceoutboxinventory.h      llpanelmediasettingsgeneral.h      llpanelmediasettingspermissions.h      llpanelmediasettingssecurity.h @@ -1007,6 +1021,7 @@ set(viewer_HEADER_FILES      llphysicsshapebuilderutil.h      llplacesinventorybridge.h      llplacesinventorypanel.h +    llplacesfolderview.h      llpolymesh.h      llpolymorph.h      llpopupview.h diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 73df064ab2..51211a8ce5 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -46,11 +46,11 @@             available_in_toybox="true"             icon="Command_Chat_Icon"             label_ref="Command_Chat_Label" -           tooltip_ref="Command_Chat_Tooltip" +           tooltip_ref="Command_Conversations_Tooltip"             execute_function="Floater.ToggleOrBringToFront" -           execute_parameters="chat_bar" +           execute_parameters="im_container"             is_running_function="Floater.IsOpen" -           is_running_parameters="chat_bar" +           is_running_parameters="im_container"             />    <command name="compass"             available_in_toybox="false" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 1bf773bb9e..61bc58b1df 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2,6 +2,28 @@  <llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="llsd.xsd">  <map> +    <key>IMShowTime</key> +    <map> +      <key>Comment</key> +      <string>Enable(disable) timestamp showing in the chat.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map> +    <key>IMShowNamesForP2PConv</key> +    <map> +      <key>Comment</key> +      <string>Enable(disable) showing of a names in the chat.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>  	<key>CrashHostUrl</key>      <map>        <key>Comment</key> @@ -1595,17 +1617,6 @@        <key>Value</key>        <integer>1</integer>      </map> -    <key>ChatWindow</key> -    <map> -      <key>Comment</key> -      <string>Show chat in multiple windows(by default) or in one multi-tabbed window(requires restart)</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>S32</string> -      <key>Value</key> -      <integer>0</integer> -    </map>      <key>CheesyBeacon</key>      <map>        <key>Comment</key> @@ -1628,6 +1639,17 @@        <key>Value</key>        <string />      </map> +    <key>NearbyChatIsNotTornOff</key> +    <map> +      <key>Comment</key> +      <string>saving torn-off state of the nearby chat between sessions</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>      <key>CloseChatOnReturn</key>      <map>        <key>Comment</key> @@ -8090,7 +8112,7 @@      <key>Type</key>      <string>F32</string>      <key>Value</key> -    <real>0</real> +    <real>-0.007</real>    </map>    <key>RenderShadowOffsetError</key>    <map> @@ -9835,7 +9857,7 @@  	<key>ShowScriptErrorsLocation</key>      <map>        <key>Comment</key> -      <string>Show script error in chat or window</string> +      <string>Show script error in chat (0) or window (1).</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -10019,6 +10041,39 @@        <key>Value</key>        <integer>2</integer>      </map> +    <key>BlockPeopleSortOrder</key> +    <map> +      <key>Comment</key> +      <string>Specifies sort order for recent people (0 = by name, 1 = by type)</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>2</integer> +    </map> +    <key>CallLogSortOrder</key> +    <map> +      <key>Comment</key> +      <string>Specifies sort order for Call Log (0 = by name, 1 = by date)</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>2</integer> +    </map> +    <key>SortFriendsFirst</key> +    <map> +      <key>Comment</key> +      <string>Specifies whether friends will be sorted first in Call Log</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>      <key>ShowPGSearchAll</key>          <map>        <key>Comment</key> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 143126b334..1f637ef3ff 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -22,6 +22,61 @@          <key>Value</key>              <string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed.  Your message will still be shown in their IM panel for later viewing.</string>          </map> +    <key>ConversationsExpandMessagePaneFirst</key> +    <map> +        <key>Comment</key> +            <string>Expand either messages or conversations list pane from Conversations compact mode.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>1</integer> +    </map> +    <key>ConversationsListPaneCollapsed</key> +    <map> +        <key>Comment</key> +            <string>Stores the expanded/collapsed state of the conversations list pane in Conversations floater.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +    </map> +    <key>ConversationsListPaneWidth</key> +    <map> +        <key>Comment</key> +            <string>Conversations floater list pane width.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>268</integer> +    </map> +    <key>ConversationsMessagePaneCollapsed</key> +    <map> +        <key>Comment</key> +            <string>Stores the expanded/collapsed state of Conversations floater message pane.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +    </map> +    <key>ConversationsMessagePaneWidth</key> +    <map> +        <key>Comment</key> +            <string>Conversations floater message pane width.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>412</integer> +    </map>      <key>InstantMessageLogPath</key>          <map>          <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 8db4cb58cf..12706f130b 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -34,10 +34,10 @@ out vec4 frag_color;  VARYING vec4 vertex_color;  VARYING vec2 vary_texcoord0; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3;  uniform sampler2DRect depthMap;  uniform mat4 shadow_matrix[6]; @@ -58,22 +58,22 @@ uniform float shadow_bias;  uniform mat4 inv_proj; -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc)  {  	stc.xyz /= stc.w;  	stc.z += shadow_bias; - -	stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here +		 +	stc.x = floor(stc.x*shadow_res.x + fract(stc.y*shadow_res.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here -	float cs = shadow2DRect(shadowMap, stc.xyz).x; +	float cs = shadow2D(shadowMap, stc.xyz).x;  	float shadow = cs; - -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; -                         -        return shadow*0.2; +	 +    shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +    shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; +    shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +    shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; +                        +    return shadow*0.2;  } @@ -99,8 +99,7 @@ void main()  		if (spos.z < near_split.z)  		{  			lpos = shadow_matrix[3]*spos; -			lpos.xy *= shadow_res; - +			  			float w = 1.0;  			w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;  			shadow += pcfShadow(shadowMap3, lpos)*w; @@ -111,8 +110,7 @@ void main()  		if (spos.z < near_split.y && spos.z > far_split.z)  		{  			lpos = shadow_matrix[2]*spos; -			lpos.xy *= shadow_res; - +			  			float w = 1.0;  			w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;  			w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -123,8 +121,7 @@ void main()  		if (spos.z < near_split.x && spos.z > far_split.y)  		{  			lpos = shadow_matrix[1]*spos; -			lpos.xy *= shadow_res; - +			  			float w = 1.0;  			w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;  			w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; @@ -135,8 +132,7 @@ void main()  		if (spos.z > far_split.x)  		{  			lpos = shadow_matrix[0]*spos; -			lpos.xy *= shadow_res; -				 +							  			float w = 1.0;  			w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl index 33958a5010..228dc104ac 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl @@ -31,17 +31,16 @@ out vec4 frag_color;  #define frag_color gl_FragColor  #endif -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3;  uniform sampler2DRect depthMap;  uniform sampler2D diffuseMap;  uniform mat4 shadow_matrix[6];  uniform vec4 shadow_clip;  uniform vec2 screen_res; -uniform vec2 shadow_res;  vec3 atmosLighting(vec3 light);  vec3 scaleSoftClip(vec3 light); @@ -54,6 +53,7 @@ VARYING vec3 vary_pointlight_col;  VARYING vec2 vary_texcoord0;  VARYING vec4 vertex_color; +uniform vec2 shadow_res;  uniform float shadow_bias;  uniform mat4 inv_proj; @@ -71,22 +71,22 @@ vec4 getPosition(vec2 pos_screen)  	return pos;  } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc)  {  	stc.xyz /= stc.w;  	stc.z += shadow_bias; -	stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here +	stc.x = floor(stc.x*shadow_res.x + fract(stc.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here -	float cs = shadow2DRect(shadowMap, stc.xyz).x; +	float cs = shadow2D(shadowMap, stc.xyz).x;  	float shadow = cs; - -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; +	 +    shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +    shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; +    shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +    shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; -        return shadow*0.2; +    return shadow*0.2;  } @@ -112,8 +112,7 @@ void main()  		if (spos.z < near_split.z)  		{  			lpos = shadow_matrix[3]*spos; -			lpos.xy *= shadow_res; - +			  			float w = 1.0;  			w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;  			shadow += pcfShadow(shadowMap3, lpos)*w; @@ -124,8 +123,7 @@ void main()  		if (spos.z < near_split.y && spos.z > far_split.z)  		{  			lpos = shadow_matrix[2]*spos; -			lpos.xy *= shadow_res; - +			  			float w = 1.0;  			w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;  			w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -136,8 +134,7 @@ void main()  		if (spos.z < near_split.x && spos.z > far_split.y)  		{  			lpos = shadow_matrix[1]*spos; -			lpos.xy *= shadow_res; - +			  			float w = 1.0;  			w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;  			w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; @@ -148,8 +145,7 @@ void main()  		if (spos.z > far_split.x)  		{  			lpos = shadow_matrix[0]*spos; -			lpos.xy *= shadow_res; -				 +							  			float w = 1.0;  			w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl index 2093fc37dc..c3950a10e1 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl @@ -33,17 +33,16 @@ out vec4 frag_color;  uniform float minimum_alpha; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3;  uniform sampler2DRect depthMap;  uniform sampler2D diffuseMap;  uniform mat4 shadow_matrix[6];  uniform vec4 shadow_clip;  uniform vec2 screen_res; -uniform vec2 shadow_res;  vec3 atmosLighting(vec3 light);  vec3 scaleSoftClip(vec3 light); @@ -55,6 +54,8 @@ VARYING vec3 vary_position;  VARYING vec3 vary_pointlight_col;  VARYING vec2 vary_texcoord0; +uniform vec2 shadow_res; +  uniform float shadow_bias;  uniform mat4 inv_proj; @@ -72,20 +73,20 @@ vec4 getPosition(vec2 pos_screen)  	return pos;  } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc)  {  	stc.xyz /= stc.w;  	stc.z += shadow_bias; -	stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here +	stc.x = floor(stc.x*shadow_res.x + fract(stc.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here +	float cs = shadow2D(shadowMap, stc.xyz).x; -	float cs = shadow2DRect(shadowMap, stc.xyz).x;  	float shadow = cs; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; +        shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +        shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; +        shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +        shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;          return shadow*0.2;  } @@ -120,8 +121,7 @@ void main()  		if (spos.z < near_split.z)  		{  			lpos = shadow_matrix[3]*spos; -			lpos.xy *= shadow_res; - +			  			float w = 1.0;  			w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;  			shadow += pcfShadow(shadowMap3, lpos)*w; @@ -132,8 +132,7 @@ void main()  		if (spos.z < near_split.y && spos.z > far_split.z)  		{  			lpos = shadow_matrix[2]*spos; -			lpos.xy *= shadow_res; - +			  			float w = 1.0;  			w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;  			w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -144,8 +143,7 @@ void main()  		if (spos.z < near_split.x && spos.z > far_split.y)  		{  			lpos = shadow_matrix[1]*spos; -			lpos.xy *= shadow_res; - +			  			float w = 1.0;  			w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;  			w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; @@ -156,8 +154,7 @@ void main()  		if (spos.z > far_split.x)  		{  			lpos = shadow_matrix[0]*spos; -			lpos.xy *= shadow_res; -				 +							  			float w = 1.0;  			w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index db3d760359..c1495b145e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -35,10 +35,10 @@ out vec4 frag_color;  uniform sampler2DRect depthMap;  uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3;  uniform sampler2DShadow shadowMap4;  uniform sampler2DShadow shadowMap5; @@ -55,10 +55,10 @@ VARYING vec2 vary_fragcoord;  uniform mat4 inv_proj;  uniform vec2 screen_res; -uniform vec2 shadow_res;  uniform vec2 proj_shadow_res;  uniform vec3 sun_dir; +uniform vec2 shadow_res;  uniform float shadow_bias;  uniform float shadow_offset; @@ -78,30 +78,31 @@ vec4 getPosition(vec2 pos_screen)  	return pos;  } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)  {  	stc.xyz /= stc.w; -	stc.z += shadow_bias*scl; +	stc.z += shadow_bias; -	stc.x = floor(stc.x + fract(pos_screen.y*0.666666666)); // add some jitter to X sample pos according to Y to disguise the snapping going on here +	stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666))/shadow_res.x; // add some jitter to X sample pos according to Y to disguise the snapping going on here +	float cs = shadow2D(shadowMap, stc.xyz).x; -	float cs = shadow2DRect(shadowMap, stc.xyz).x;  	float shadow = cs; -	shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; -	shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; -	shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, 1.5, 0.0)).x; -	shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, -1.5, 0.0)).x; +	shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +	shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; +	shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +	shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + -        return shadow*0.2; +    return shadow*0.2;  } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)  {  	stc.xyz /= stc.w;  	stc.z += spot_shadow_bias*scl;  	stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap -	 +  	float cs = shadow2D(shadowMap, stc.xyz).x;  	float shadow = cs; @@ -162,8 +163,7 @@ void main()  			if (spos.z < near_split.z)  			{  				lpos = shadow_matrix[3]*spos; -				lpos.xy *= shadow_res; - +				  				float w = 1.0;  				w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;  				shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; @@ -174,8 +174,7 @@ void main()  			if (spos.z < near_split.y && spos.z > far_split.z)  			{  				lpos = shadow_matrix[2]*spos; -				lpos.xy *= shadow_res; - +				  				float w = 1.0;  				w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;  				w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -186,7 +185,6 @@ void main()  			if (spos.z < near_split.x && spos.z > far_split.y)  			{  				lpos = shadow_matrix[1]*spos; -				lpos.xy *= shadow_res;  				float w = 1.0;  				w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; @@ -198,7 +196,6 @@ void main()  			if (spos.z > far_split.x)  			{  				lpos = shadow_matrix[0]*spos; -				lpos.xy *= shadow_res;  				float w = 1.0;  				w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; @@ -237,11 +234,11 @@ void main()  	//spotlight shadow 1  	vec4 lpos = shadow_matrix[4]*spos; -	frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen);  +	frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8, pos_screen);   	//spotlight shadow 2  	lpos = shadow_matrix[5]*spos; -	frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen);  +	frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8, pos_screen);   	//frag_color.rgb = pos.xyz;  	//frag_color.b = shadow; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index dfe108eb01..039fca9df2 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -34,10 +34,10 @@ out vec4 frag_color;  uniform sampler2DRect depthMap;  uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3;  uniform sampler2DShadow shadowMap4;  uniform sampler2DShadow shadowMap5;  uniform sampler2D noiseMap; @@ -55,10 +55,11 @@ VARYING vec2 vary_fragcoord;  uniform mat4 inv_proj;  uniform vec2 screen_res; -uniform vec2 shadow_res;  uniform vec2 proj_shadow_res;  uniform vec3 sun_dir; +uniform vec2 shadow_res; +  uniform float shadow_bias;  uniform float shadow_offset; @@ -139,30 +140,30 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)  	return min(ret, 1.0);  } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)  {  	stc.xyz /= stc.w; -	stc.z += shadow_bias*scl; +	stc.z += shadow_bias; -	stc.x = floor(stc.x + fract(pos_screen.y*0.666666666)); +	stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666))/shadow_res.x; +	float cs = shadow2D(shadowMap, stc.xyz).x; -	float cs = shadow2DRect(shadowMap, stc.xyz).x;  	float shadow = cs; -	shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; -        shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; -                         +	shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +    shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; +    shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; +    shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; +	                   return shadow*0.2;  } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)  {  	stc.xyz /= stc.w;  	stc.z += spot_shadow_bias*scl;  	stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap -	 +		  	float cs = shadow2D(shadowMap, stc.xyz).x;  	float shadow = cs; @@ -223,8 +224,7 @@ void main()  			if (spos.z < near_split.z)  			{  				lpos = shadow_matrix[3]*spos; -				lpos.xy *= shadow_res; - +				  				float w = 1.0;  				w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;  				shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; @@ -235,8 +235,7 @@ void main()  			if (spos.z < near_split.y && spos.z > far_split.z)  			{  				lpos = shadow_matrix[2]*spos; -				lpos.xy *= shadow_res; - +				  				float w = 1.0;  				w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;  				w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -247,8 +246,7 @@ void main()  			if (spos.z < near_split.x && spos.z > far_split.y)  			{  				lpos = shadow_matrix[1]*spos; -				lpos.xy *= shadow_res; - +				  				float w = 1.0;  				w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;  				w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; @@ -259,8 +257,7 @@ void main()  			if (spos.z > far_split.x)  			{  				lpos = shadow_matrix[0]*spos; -				lpos.xy *= shadow_res; -				 +								  				float w = 1.0;  				w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; @@ -298,11 +295,11 @@ void main()  	//spotlight shadow 1  	vec4 lpos = shadow_matrix[4]*spos; -	frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen); +	frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8, pos_screen);  	//spotlight shadow 2  	lpos = shadow_matrix[5]*spos; -	frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen); +	frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8, pos_screen);  	//frag_color.rgb = pos.xyz;  	//frag_color.b = shadow; diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 447836910d..f187318c0f 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -54,7 +54,7 @@  #include "llmorphview.h"  #include "llmoveview.h"  #include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llnotificationsutil.h"  #include "llpanelpathfindingrebakenavmesh.h"  #include "llpaneltopinfobar.h" @@ -1911,7 +1911,7 @@ void LLAgent::startTyping()  	{  		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);  	} -	LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); +	LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE);  }  //----------------------------------------------------------------------------- @@ -1923,7 +1923,7 @@ void LLAgent::stopTyping()  	{  		clearRenderState(AGENT_STATE_TYPING);  		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); -		LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); +		LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);  	}  } diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index e2417cdddb..e31e39dca2 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -342,7 +342,7 @@ void LLLibraryOutfitsFetch::folderDone()  	}  	mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); -	mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); +	mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING, false);  	// If Library->Clothing->Initial Outfits exists, use that.  	LLNameCategoryCollector matchFolderFunctor("Initial Outfits"); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 6d67e098a6..510abf198a 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2330,7 +2330,7 @@ void LLAppearanceMgr::copyLibraryGestures()  	// Copy gestures  	LLUUID lib_gesture_cat_id = -		gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE,false,true); +		gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_GESTURE,false);  	if (lib_gesture_cat_id.isNull())  	{  		llwarns << "Unable to copy gestures, source category not found" << llendl; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index cb69048c60..08a1a237f5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -59,6 +59,7 @@  #include "llares.h"   #include "llcurl.h"  #include "llcalc.h" +#include "llconversationlog.h"  #include "lltexturestats.h"  #include "lltexturestats.h"  #include "llviewerwindow.h" @@ -1832,6 +1833,9 @@ bool LLAppViewer::cleanup()  	// save mute list. gMuteList used to also be deleted here too.  	LLMuteList::getInstance()->cache(gAgent.getID()); +	//save call log list +	LLConversationLog::instance().cache(); +  	if (mPurgeOnExit)  	{  		llinfos << "Purging all cache files on exit" << llendflush; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index fdd4565e50..93e8b9ca40 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -235,7 +235,7 @@ void LLAvatarActions::startCall(const LLUUID& id)  }  // static -void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids) +void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids, const LLUUID& floater_id)  {  	if (ids.size() == 0)  	{ @@ -252,7 +252,7 @@ void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids)  	// create the new ad hoc voice session  	const std::string title = LLTrans::getString("conference-title");  	LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, -										   ids[0], id_array, true); +										   ids[0], id_array, true, floater_id);  	if (session_id == LLUUID::null)  	{  		return; @@ -285,7 +285,7 @@ bool LLAvatarActions::canCall()  }  // static -void LLAvatarActions::startConference(const uuid_vec_t& ids) +void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& floater_id)  {  	// *HACK: Copy into dynamic array  	LLDynamicArray<LLUUID> id_array; @@ -294,7 +294,7 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids)  		id_array.push_back(*it);  	}  	const std::string title = LLTrans::getString("conference-title"); -	LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array); +	LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array, false, floater_id);  	if (session_id != LLUUID::null)  	{  		LLIMFloater::show(session_id); @@ -529,23 +529,6 @@ namespace action_give_inventory  		return acceptable;  	} -	static void build_residents_string(const std::vector<LLAvatarName> avatar_names, std::string& residents_string) -	{ -		llassert(avatar_names.size() > 0); - -		const std::string& separator = LLTrans::getString("words_separator"); -		for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; ) -		{ -			LLAvatarName av_name = *it; -			residents_string.append(av_name.mDisplayName); -			if	(++it == avatar_names.end()) -			{ -				break; -			} -			residents_string.append(separator); -		} -	} -  	static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)  	{  		llassert(inventory_selected_uuids.size() > 0); @@ -681,7 +664,7 @@ namespace action_give_inventory  		}  		std::string residents; -		build_residents_string(avatar_names, residents); +		LLAvatarActions::buildResidentsString(avatar_names, residents);  		std::string items;  		build_items_string(inventory_selected_uuids, items); @@ -712,28 +695,51 @@ namespace action_give_inventory  	}  } +// static +void LLAvatarActions::buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string) +{ +	llassert(avatar_names.size() > 0); +	const std::string& separator = LLTrans::getString("words_separator"); +	for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; ) +	{ +		LLAvatarName av_name = *it; +		residents_string.append(av_name.mDisplayName); +		if	(++it == avatar_names.end()) +		{ +			break; +		} +		residents_string.append(separator); +	} +}  //static  std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()  { -	std::set<LLUUID> inventory_selected_uuids; +	std::set<LLFolderViewItem*> inventory_selected;  	LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();  	if (active_panel)  	{ -		inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList(); +		inventory_selected= active_panel->getRootFolder()->getSelectionList();  	} -	if (inventory_selected_uuids.empty()) +	if (inventory_selected.empty())  	{  		LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");  		if (sidepanel_inventory)  		{ -			inventory_selected_uuids = sidepanel_inventory->getInboxSelectionList(); +			inventory_selected= sidepanel_inventory->getInboxSelectionList();  		}  	} +	std::set<LLUUID> inventory_selected_uuids; +	for (std::set<LLFolderViewItem*>::iterator it = inventory_selected.begin(), end_it = inventory_selected.end(); +		it != end_it; +		++it) +	{ +		inventory_selected_uuids.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +	}  	return inventory_selected_uuids;  } @@ -769,15 +775,15 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL  	// check selection in the panel  	LLFolderView* root_folder = inv_panel->getRootFolder(); -	const std::set<LLUUID> inventory_selected_uuids = root_folder->getSelectionList(); -	if (inventory_selected_uuids.empty()) return false; // nothing selected +	const std::set<LLFolderViewItem*> inventory_selected = root_folder->getSelectionList(); +	if (inventory_selected.empty()) return false; // nothing selected  	bool can_share = true; -	std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); -	const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end(); +	std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin(); +	const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end();  	for (; it != it_end; ++it)  	{ -		LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); +		LLViewerInventoryCategory* inv_cat = gInventory.getCategory(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID());  		// any category can be offered.  		if (inv_cat)  		{ @@ -785,9 +791,9 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL  		}  		// check if inventory item can be given -		LLFolderViewItem* item = root_folder->getItemByID(*it); +		LLFolderViewItem* item = *it;  		if (!item) return false; -		LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getListener()); +		LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getViewModelItem());  		if (bridge && bridge->canShare())  		{  			continue; @@ -820,6 +826,26 @@ void LLAvatarActions::toggleBlock(const LLUUID& id)  }  // static +void LLAvatarActions::toggleMuteVoice(const LLUUID& id) +{ +	std::string name; +	gCacheName->getFullName(id, name); // needed for mute + +	LLMuteList* mute_list = LLMuteList::getInstance(); +	bool is_muted = mute_list->isMuted(id, LLMute::flagVoiceChat); + +	LLMute mute(id, name, LLMute::AGENT); +	if (!is_muted) +	{ +		mute_list->add(mute, LLMute::flagVoiceChat); +	} +	else +	{ +		mute_list->remove(mute, LLMute::flagVoiceChat); +	} +} + +// static  bool LLAvatarActions::canOfferTeleport(const LLUUID& id)  {  	// First use LLAvatarTracker::isBuddy() @@ -1015,7 +1041,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri  	LLSD payload;  	payload["from_id"] = target_id; -	payload["SUPPRESS_TOAST"] = true;  	LLNotificationsUtil::add("FriendshipOffered", args, payload);  } @@ -1034,6 +1059,12 @@ bool LLAvatarActions::isBlocked(const LLUUID& id)  }  // static +bool LLAvatarActions::isVoiceMuted(const LLUUID& id) +{ +	return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); +} + +// static  bool LLAvatarActions::canBlock(const LLUUID& id)  {  	std::string full_name; diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 748b7cb3d1..259e87c336 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -34,6 +34,7 @@  #include <string>  #include <vector> +class LLAvatarName;  class LLInventoryPanel;  class LLFloater; @@ -81,14 +82,14 @@ public:  	static void startCall(const LLUUID& id);  	/** -	 * Start an ad-hoc conference voice call with multiple users +	 * Start an ad-hoc conference voice call with multiple users in a specific IM floater.  	 */ -	static void startAdhocCall(const uuid_vec_t& ids); +	static void startAdhocCall(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null);  	/** -	 * Start conference chat with the given avatars. +	 * Start conference chat with the given avatars in a specific IM floater.  	 */ -	static void startConference(const uuid_vec_t& ids); +	static void startConference(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null);  	/**  	 * Show avatar profile. @@ -124,6 +125,11 @@ public:  	static void toggleBlock(const LLUUID& id);  	/** +	 * Block/unblock the avatar voice. +	 */ +	static void toggleMuteVoice(const LLUUID& id); + +	/**  	 * Return true if avatar with "id" is a friend  	 */  	static bool isFriend(const LLUUID& id); @@ -134,6 +140,11 @@ public:  	static bool isBlocked(const LLUUID& id);  	/** +	 * @return true if the avatar voice is blocked +	 */ +	static bool isVoiceMuted(const LLUUID& id); + +	/**  	 * @return true if you can block the avatar  	 */  	static bool canBlock(const LLUUID& id); @@ -198,6 +209,14 @@ public:  	 */  	static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL); +	/** +	 * Builds a string of residents' display names separated by "words_separator" string. +	 * +	 * @param avatar_names - a vector of given avatar names from which resulting string is built +	 * @param residents_string - the resulting string +	 */ +	static void buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string); +  	static std::set<LLUUID> getInventorySelectedUUIDs();  private: diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index b539ac38ed..b539ac38ed 100644..100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 30eecfe323..7b5229b5e6 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -38,6 +38,7 @@  #include "llavatarnamecache.h"  #include "llavatariconctrl.h"  #include "lloutputmonitorctrl.h" +#include "lltooldraganddrop.h"  bool LLAvatarListItem::sStaticInitialized = false;  S32 LLAvatarListItem::sLeftPadding = 0; @@ -334,6 +335,61 @@ BOOL LLAvatarListItem::handleDoubleClick(S32 x, S32 y, MASK mask)  	return LLPanel::handleDoubleClick(x, y, mask);  } +BOOL LLAvatarListItem::handleMouseDown(S32 x, S32 y, MASK mask) +{ +	if (LLUICtrl::handleMouseDown(x, y, mask)) +	{ +		return TRUE; +	} + +	gFocusMgr.setMouseCapture(this); + +	S32 screen_x; +	S32 screen_y; +	localPointToScreen(x, y, &screen_x, &screen_y); +	LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y); + +	return TRUE; +} + +BOOL LLAvatarListItem::handleMouseUp( S32 x, S32 y, MASK mask ) +{ +	if (LLUICtrl::childrenHandleMouseUp(x, y, mask)) +	{ +		return TRUE; +	} + +	if(hasMouseCapture()) +	{ +		gFocusMgr.setMouseCapture(NULL); +	} +	return TRUE; +} + +BOOL LLAvatarListItem::handleHover(S32 x, S32 y, MASK mask) +{ +	bool handled = hasMouseCapture(); +	if(handled) +	{ +		S32 screen_x; +		S32 screen_y; +		localPointToScreen(x, y, &screen_x, &screen_y); + +		if(LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) +		{ +			// First, create the global drag and drop object +			std::vector<EDragAndDropType> types; +			uuid_vec_t cargo_ids; +			types.push_back(DAD_PERSON); +			cargo_ids.push_back(mAvatarId); +			LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_PEOPLE; +			LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src); +		} +	} + +	return handled; +} +  void LLAvatarListItem::setValue( const LLSD& value )  {  	if (!value.isMap()) return;; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index c95ac39696..28a50870d4 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -112,6 +112,9 @@ public:  	void onProfileBtnClick();  	/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); +	/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); +	/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); +	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);  protected:  	/** diff --git a/indra/newview/llblockedlistitem.cpp b/indra/newview/llblockedlistitem.cpp new file mode 100644 index 0000000000..d9afd2b629 --- /dev/null +++ b/indra/newview/llblockedlistitem.cpp @@ -0,0 +1,114 @@ +/** + * @file llviewerobjectlistitem.cpp + * @brief viewer object list item implementation + * + * Class LLPanelInventoryListItemBase displays inventory item as an element + * of LLInventoryItemsList. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llblockedlistitem.h" + +// llui +#include "lliconctrl.h" +#include "lltextbox.h" +#include "lltextutil.h" + +// newview +#include "llavatariconctrl.h" +#include "llgroupiconctrl.h" +#include "llinventoryicon.h" +#include "llviewerobject.h" + +LLBlockedListItem::LLBlockedListItem(const LLMute* item) +:	LLPanel(), +	mItemID(item->mID), +	mItemName(item->mName), +	mMuteType(item->mType) +{ +	buildFromFile("panel_blocked_list_item.xml"); +} + +BOOL LLBlockedListItem::postBuild() +{ +	mTitleCtrl = getChild<LLTextBox>("item_name"); +	mTitleCtrl->setValue(mItemName); + +	switch (mMuteType) +	{ +	case LLMute::AGENT: +	case LLMute::EXTERNAL: +		{ +			LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); +			avatar_icon->setVisible(TRUE); +			avatar_icon->setValue(mItemID); +		} +		break; +	case LLMute::GROUP: +		{ +			LLGroupIconCtrl* group_icon = getChild<LLGroupIconCtrl>("group_icon"); +			group_icon->setVisible(TRUE); +			group_icon->setValue(mItemID); +		} +		break; +	case LLMute::OBJECT: +	case LLMute::BY_NAME: +		getChild<LLUICtrl>("object_icon")->setVisible(TRUE); +		break; + +	default: +		break; +	} + +	return TRUE; +} + +void LLBlockedListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ +	getChildView("hovered_icon")->setVisible(true); +	LLPanel::onMouseEnter(x, y, mask); +} + +void LLBlockedListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ +	getChildView("hovered_icon")->setVisible(false); +	LLPanel::onMouseLeave(x, y, mask); +} + +void LLBlockedListItem::setValue(const LLSD& value) +{ +	if (!value.isMap() || !value.has("selected")) +	{ +		return; +	} + +	getChildView("selected_icon")->setVisible(value["selected"]); +} + +void LLBlockedListItem::highlightName(const std::string& highlited_text) +{ +	LLStyle::Params params; +	LLTextUtil::textboxSetHighlightedVal(mTitleCtrl, params, mItemName, highlited_text); +} diff --git a/indra/newview/llblockedlistitem.h b/indra/newview/llblockedlistitem.h new file mode 100644 index 0000000000..05409e8a3b --- /dev/null +++ b/indra/newview/llblockedlistitem.h @@ -0,0 +1,73 @@ +/** + * @file llviewerobjectlistitem.h + * @brief viewer object list item header file + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ +#ifndef LLVIEWEROBJECTLISTITEM_H_ +#define LLVIEWEROBJECTLISTITEM_H_ + +#include "llmutelist.h" +#include "llpanel.h" +#include "llstyle.h" +#include "lltextbox.h" +#include "lliconctrl.h" + +/** + * This class represents items of LLBlockList, which represents + * contents of LLMuteList. LLMuteList "consists" of LLMute items. + * Each LLMute represents either blocked avatar or object and + * stores info about mute type (avatar or object) + * + * Each item consists if object/avatar icon and object/avatar name + * + * To create a blocked list item just need to pass LLMute pointer + * and appropriate block list item will be created depending on + * LLMute type (LLMute::EType) and other LLMute's info + */ +class LLBlockedListItem : public LLPanel +{ +public: + +	LLBlockedListItem(const LLMute* item); +	virtual BOOL postBuild(); + +	void onMouseEnter(S32 x, S32 y, MASK mask); +	void onMouseLeave(S32 x, S32 y, MASK mask); + +	virtual void setValue(const LLSD& value); + +	void 					highlightName(const std::string& highlited_text); +	const std::string&		getName() const { return mItemName; } +	const LLMute::EType&	getType() const { return mMuteType; } +	const LLUUID&			getUUID() const { return mItemID;	} + +private: + +	LLTextBox*		mTitleCtrl; +	const LLUUID	mItemID; +	std::string		mItemName; +	LLMute::EType	mMuteType; + +}; + +#endif /* LLVIEWEROBJECTLISTITEM_H_ */ diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp new file mode 100644 index 0000000000..066cb71677 --- /dev/null +++ b/indra/newview/llblocklist.cpp @@ -0,0 +1,284 @@ +/** + * @file llblocklist.cpp + * @brief List of the blocked avatars and objects. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llblocklist.h" + +#include "llavataractions.h" +#include "llblockedlistitem.h" +#include "llfloatersidepanelcontainer.h" +#include "llviewermenu.h" + +static LLDefaultChildRegistry::Register<LLBlockList> r("block_list"); + +static const LLBlockListNameComparator 		NAME_COMPARATOR; +static const LLBlockListNameTypeComparator	NAME_TYPE_COMPARATOR; + +LLBlockList::LLBlockList(const Params& p) +:	LLFlatListViewEx(p), + 	mSelectedItem(NULL), + 	mDirty(true) +{ + +	LLMuteList::getInstance()->addObserver(this); + +	// Set up context menu. +	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + +	registrar.add		("Block.Action",	boost::bind(&LLBlockList::onCustomAction,	this, _2)); +	enable_registrar.add("Block.Enable",	boost::bind(&LLBlockList::isActionEnabled,	this, _2)); + +	LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( +									"menu_people_blocked_gear.xml", +									gMenuHolder, +									LLViewerMenuHolderGL::child_registry_t::instance()); +	if(context_menu) +	{ +		mContextMenu = context_menu->getHandle(); +	} +} + +LLBlockList::~LLBlockList() +{ +	if (mContextMenu.get()) +	{ +		mContextMenu.get()->die(); +	} + +	LLMuteList::getInstance()->removeObserver(this); +} + +BOOL LLBlockList::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ +	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); + +	LLToggleableMenu* context_menu = mContextMenu.get(); +	if (context_menu && size()) +	{ +		context_menu->buildDrawLabels(); +		context_menu->updateParent(LLMenuGL::sMenuContainer); +		LLMenuGL::showPopup(this, context_menu, x, y); +	} + +	return handled; +} + +void LLBlockList::setNameFilter(const std::string& filter) +{ +	std::string filter_upper = filter; +	LLStringUtil::toUpper(filter_upper); +	if (mNameFilter != filter_upper) +	{ +		mNameFilter = filter_upper; +		setDirty(); +	} +} + +void LLBlockList::sortByName() +{ +	setComparator(&NAME_COMPARATOR); +	sort(); +} + +void LLBlockList::sortByType() +{ +	setComparator(&NAME_TYPE_COMPARATOR); +	sort(); +} + +void LLBlockList::draw() +{ +	if (mDirty) +	{ +		refresh(); +	} + +	LLFlatListView::draw(); +} + +void LLBlockList::addNewItem(const LLMute* mute) +{ +	LLBlockedListItem* item = new LLBlockedListItem(mute); +	if (!mNameFilter.empty()) +	{ +		item->highlightName(mNameFilter); +	} +	addItem(item, item->getUUID(), ADD_BOTTOM); +} + +void LLBlockList::refresh() +{ +	bool have_filter = !mNameFilter.empty(); + +	// save selection to restore it after list rebuilt +	LLUUID selected = getSelectedUUID(); + +	// calling refresh may be initiated by removing currently selected item +	// so select next item and save the selection to restore it after list rebuilt +	if (!selectNextItemPair(false, true)) +	{ +		selectNextItemPair(true, true); +	} +	LLUUID next_selected = getSelectedUUID(); + +	clear(); + +	std::vector<LLMute> mutes = LLMuteList::instance().getMutes(); +	std::vector<LLMute>::const_iterator mute_it = mutes.begin(); + +	for (; mute_it != mutes.end(); ++mute_it) +	{ +		if (have_filter && !findInsensitive(mute_it->mName, mNameFilter)) +			continue; + +		addNewItem(&*mute_it); +	} + +	if (getItemPair(selected)) +	{ +		// restore previously selected item +		selectItemPair(getItemPair(selected), true); +	} +	else if (getItemPair(next_selected)) +	{ +		// previously selected item was removed, so select next item +		selectItemPair(getItemPair(next_selected), true); +	} + +	// Sort the list. +	sort(); + +	setDirty(false); +} + +bool LLBlockList::findInsensitive(std::string haystack, const std::string& needle_upper) +{ +    LLStringUtil::toUpper(haystack); +    return haystack.find(needle_upper) != std::string::npos; +} + +LLBlockedListItem* LLBlockList::getBlockedItem() const +{ +	LLPanel* panel = LLFlatListView::getSelectedItem(); +	LLBlockedListItem* item = dynamic_cast<LLBlockedListItem*>(panel); +	return item; +} + +bool LLBlockList::isActionEnabled(const LLSD& userdata) +{ +	bool action_enabled = true; + +	const std::string command_name = userdata.asString(); + +	if ("profile_item" == command_name) +	{ +		LLBlockedListItem* item = getBlockedItem(); +		action_enabled = item && (LLMute::AGENT == item->getType()); +	} + +	if ("unblock_item" == command_name) +	{ +		action_enabled = getSelectedItem() != NULL; +	} + +	return action_enabled; +} + +void LLBlockList::onCustomAction(const LLSD& userdata) +{ +	if (!isActionEnabled(userdata)) +	{ +		return; +	} + +	LLBlockedListItem* item = getBlockedItem(); +	const std::string command_name = userdata.asString(); + +	if ("unblock_item" == command_name) +	{ +		LLMute mute(item->getUUID(), item->getName()); +		LLMuteList::getInstance()->remove(mute); +	} +	else if ("profile_item" == command_name) +	{ +		switch(item->getType()) +		{ + +		case LLMute::AGENT: +			LLAvatarActions::showProfile(item->getUUID()); +			break; + +		default: +			break; +		} +	} +} + +bool LLBlockListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const +{ +	const LLBlockedListItem* blocked_item1 = dynamic_cast<const LLBlockedListItem*>(item1); +	const LLBlockedListItem* blocked_item2 = dynamic_cast<const LLBlockedListItem*>(item2); + +	if (!blocked_item1 || !blocked_item2) +	{ +		llerror("blocked_item1 and blocked_item2 cannot be null", 0); +		return true; +	} + +	return doCompare(blocked_item1, blocked_item2); +} + +bool LLBlockListNameComparator::doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const +{ +	std::string name1 = blocked_item1->getName(); +	std::string name2 = blocked_item2->getName(); + +	LLStringUtil::toUpper(name1); +	LLStringUtil::toUpper(name2); + +	return name1 < name2; +} + +bool LLBlockListNameTypeComparator::doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const +{ +	LLMute::EType type1 = blocked_item1->getType(); +	LLMute::EType type2 = blocked_item2->getType(); + +	// if mute type is LLMute::BY_NAME or LLMute::OBJECT it means that this mute is an object +	bool both_mutes_are_objects = (LLMute::OBJECT == type1 || LLMute::BY_NAME == type1) && (LLMute::OBJECT == type2 || LLMute::BY_NAME == type2); + +	// mute types may be different, but since both LLMute::BY_NAME and LLMute::OBJECT types represent objects +	// it's needed to perform additional checking of both_mutes_are_objects variable +	if (type1 != type2 && !both_mutes_are_objects) +	{ +		// objects in block list go first, so return true if mute type is not an avatar +		return LLMute::AGENT != type1; +	} + +	return NAME_COMPARATOR.compare(blocked_item1, blocked_item2); +} diff --git a/indra/newview/llblocklist.h b/indra/newview/llblocklist.h new file mode 100644 index 0000000000..1a215710f4 --- /dev/null +++ b/indra/newview/llblocklist.h @@ -0,0 +1,138 @@ +/** + * @file llblocklist.h + * @brief List of the blocked avatars and objects. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ +#ifndef LLBLOCKLIST_H_ +#define LLBLOCKLIST_H_ + +#include "llflatlistview.h" +#include "lllistcontextmenu.h" +#include "llmutelist.h" +#include "lltoggleablemenu.h" + +class LLBlockedListItem; +class LLMute; + +/** + * List of blocked avatars and objects. + * This list represents contents of the LLMuteList. + * Each change in LLMuteList leads to rebuilding this list, so + * it's always in actual state. + */ +class LLBlockList: public LLFlatListViewEx, public LLMuteListObserver +{ +	LOG_CLASS(LLBlockList); +public: +	struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> +	{ +		Params(){}; +	}; + +	LLBlockList(const Params& p); +	virtual ~LLBlockList(); + +	virtual BOOL 		handleRightMouseDown(S32 x, S32 y, MASK mask); +	LLToggleableMenu*	getContextMenu() const { return mContextMenu.get(); } +	LLBlockedListItem*	getBlockedItem() const; + +	virtual void onChange() { refresh(); } +	virtual void draw(); + +	void setNameFilter(const std::string& filter); +	void sortByName(); +	void sortByType(); +	void refresh(); + +private: + +	void addNewItem(const LLMute* mute); +	void setDirty(bool dirty = true) { mDirty = dirty; } +	bool findInsensitive(std::string haystack, const std::string& needle_upper); + +	bool isActionEnabled(const LLSD& userdata); +	void onCustomAction (const LLSD& userdata); + + +	LLHandle<LLToggleableMenu>	mContextMenu; + +	LLBlockedListItem*			mSelectedItem; +	std::string 				mNameFilter; +	bool 						mDirty; + +}; + + +/* + * Abstract comparator for blocked items + */ +class LLBlockListItemComparator : public LLFlatListView::ItemComparator +{ +	LOG_CLASS(LLBlockListItemComparator); + +public: +	LLBlockListItemComparator() {}; +	virtual ~LLBlockListItemComparator() {}; + +	virtual bool compare(const LLPanel* item1, const LLPanel* item2) const; + +protected: + +	virtual bool doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const = 0; +}; + + +/* + * Compares items by name + */ +class LLBlockListNameComparator : public LLBlockListItemComparator +{ +	LOG_CLASS(LLBlockListNameComparator); + +public: +	LLBlockListNameComparator() {}; +	virtual ~LLBlockListNameComparator() {}; + +protected: + +	virtual bool doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const; +}; + +/* + * Compares items by type and then by name within type + * Objects come first then avatars + */ +class LLBlockListNameTypeComparator : public LLBlockListItemComparator +{ +	LOG_CLASS(LLBlockListNameTypeComparator); + +public: +	LLBlockListNameTypeComparator() {}; +	virtual ~LLBlockListNameTypeComparator() {}; + +protected: + +	virtual bool doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const; +}; + +#endif /* LLBLOCKLIST_H_ */ diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 6e77d1e336..9e608d2c8b 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -35,11 +35,8 @@  using namespace LLNotificationsUI; -bool LLBrowserNotification::processNotification(const LLSD& notify) +bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification)  { -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); -	if (!notification) return false; -  	LLUUID media_id = notification->getPayload()["media_id"].asUUID();  	LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id);  	if (media_instance) diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 0d55c4429a..60d60abd45 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -54,6 +54,7 @@  #include "llresmgr.h"  #include "llslurl.h"  #include "llimview.h" +#include "lltrans.h"  #include "llviewercontrol.h"  #include "llviewernetwork.h"  #include "llviewerobjectlist.h" @@ -723,12 +724,13 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,  	// Use display name only because this user is your friend  	LLSD args;  	args["NAME"] = av_name.mDisplayName; +	args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus");  	LLNotificationPtr notification;  	if (online)  	{  		notification = -			LLNotificationsUtil::add("FriendOnline", +			LLNotificationsUtil::add("FriendOnlineOffline",  									 args,  									 payload.with("respond_on_mousedown", TRUE),  									 boost::bind(&LLAvatarActions::startIM, agent_id)); @@ -736,7 +738,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,  	else  	{  		notification = -			LLNotificationsUtil::add("FriendOffline", args, payload); +			LLNotificationsUtil::add("FriendOnlineOffline", args, payload);  	}  	// If there's an open IM session with this agent, send a notification there too. diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 84e73e96fa..e3d57ab7ae 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -143,7 +143,8 @@ public:  		{  			LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT)); -			LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD().with("blocked_to_select", getAvatarId())); +			LLFloaterSidePanelContainer::showPanel("people", "panel_people", +				LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId()));  		}  	} @@ -695,6 +696,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  {  	LLFastTimer _(FTM_APPEND_MESSAGE);  	bool use_plain_text_chat_history = args["use_plain_text_chat_history"].asBoolean(); +	bool square_brackets = false; // square brackets necessary for a system messages  	llassert(mEditor);  	if (!mEditor) @@ -702,9 +704,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		return;  	} +	bool from_me = chat.mFromID == gAgent.getID();  	mEditor->setPlainText(use_plain_text_chat_history); -	if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty()) +	if (!mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty())  	{  		mUnreadChatSources.insert(chat.mFromName);  		mMoreChatPanel->setVisible(TRUE); @@ -734,16 +737,23 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  	}  	LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); +	LLColor4 name_color(txt_color); +  	LLViewerChat::getChatColor(chat,txt_color);  	LLFontGL* fontp = LLViewerChat::getChatFont();	  	std::string font_name = LLFontGL::nameFromFont(fontp);  	std::string font_size = LLFontGL::sizeFromFont(fontp);	 -	LLStyle::Params style_params; -	style_params.color(txt_color); -	style_params.readonly_color(txt_color); -	style_params.font.name(font_name); -	style_params.font.size(font_size);	 -	style_params.font.style(input_append_params.font.style); + +	LLStyle::Params body_message_params; +	body_message_params.color(txt_color); +	body_message_params.readonly_color(txt_color); +	body_message_params.font.name(font_name); +	body_message_params.font.size(font_size); +	body_message_params.font.style(input_append_params.font.style); + +	LLStyle::Params name_params(body_message_params); +	name_params.color(name_color); +	name_params.readonly_color(name_color);  	std::string prefix = chat.mText.substr(0, 4); @@ -766,29 +776,51 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  	if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC)  	{  		delimiter = LLStringUtil::null; -		style_params.font.style = "ITALIC"; +		name_params.font.style = "ITALIC";  	}  	bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY;  	// We graying out chat history by graying out messages that contains full date in a time string  	if (message_from_log)  	{ -		style_params.color(LLColor4::grey); -		style_params.readonly_color(LLColor4::grey); +		txt_color = LLColor4::grey; +		body_message_params.color(txt_color); +		body_message_params.readonly_color(txt_color); +		name_params.color(txt_color); +		name_params.readonly_color(txt_color);  	} +	bool prependNewLineState = mEditor->getText().size() != 0; + +	// compact mode: show a timestamp and name  	if (use_plain_text_chat_history)  	{ -		LLStyle::Params timestamp_style(style_params); +		square_brackets = chat.mFromName == SYSTEM_FROM; + +		LLStyle::Params timestamp_style(body_message_params); + +		// out of the timestamp +		if (args["show_time"].asBoolean()) +		{  		if (!message_from_log)  		{  			LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor");  			timestamp_style.color(timestamp_color);  			timestamp_style.readonly_color(timestamp_color);  		} -		mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getLength() != 0, timestamp_style); +			mEditor->appendText("[" + chat.mTimeStr + "] ", prependNewLineState, timestamp_style); +			prependNewLineState = false; +		} + +        // out the opening square bracket (if need) +		if (square_brackets) +		{ +			mEditor->appendText("[", prependNewLineState, body_message_params); +			prependNewLineState = false; +		} -		if (utf8str_trim(chat.mFromName).size() != 0) +		// names showing +		if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0)  		{  			// Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text.  			if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull()) @@ -798,32 +830,47 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  				// set the link for the object name to be the objectim SLapp  				// (don't let object names with hyperlinks override our objectim Url) -				LLStyle::Params link_params(style_params); +				LLStyle::Params link_params(body_message_params);  				LLColor4 link_color = LLUIColorTable::instance().getColor("HTMLLinkColor");  				link_params.color = link_color;  				link_params.readonly_color = link_color;  				link_params.is_link = true;  				link_params.link_href = url; -				mEditor->appendText(chat.mFromName + delimiter, -									false, link_params); +				mEditor->appendText(chat.mFromName + delimiter, prependNewLineState, link_params); +				prependNewLineState = false;  			}  			else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log)  			{ -				LLStyle::Params link_params(style_params); +				LLStyle::Params link_params(body_message_params);  				link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); +				if (from_me) +				{	std::string localized_name; +					bool is_localized = LLTrans::findString(localized_name, "AgentNameSubst"); +					mEditor->appendText((is_localized? localized_name:"(You)") + delimiter, +							prependNewLineState, link_params); +					prependNewLineState = false; +				} +				else +				{  				// Add link to avatar's inspector and delimiter to message. -				mEditor->appendText(std::string(link_params.link_href) + delimiter, false, link_params); +					mEditor->appendText(std::string(link_params.link_href) + delimiter, +							prependNewLineState, link_params); +					prependNewLineState = false; +				}  			}  			else  			{ -				mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, style_params); +				mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, +						prependNewLineState, body_message_params); +				prependNewLineState = false;  			}  		}  	} -	else +	else // showing timestamp and name in the expanded mode  	{ +		prependNewLineState = false;  		LLView* view = NULL;  		LLInlineViewSegment::Params p;  		p.force_newline = true; @@ -844,7 +891,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		}  		else  		{ -			view = getHeader(chat, style_params, args); +			view = getHeader(chat, name_params, args);  			if (mEditor->getLength() == 0)  				p.top_pad = 0;  			else @@ -873,41 +920,16 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		mIsLastMessageFromLog = message_from_log;  	} +	// body of the message processing + +	// notify processing  	if (chat.mNotifId.notNull())  	{  		LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId);  		if (notification != NULL)  		{  			LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( -					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history); -			//we can't set follows in xml since it broke toasts behavior -			notify_box->setFollowsLeft(); -			notify_box->setFollowsRight(); -			notify_box->setFollowsTop(); - -			ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList(); -			S32 offset = 0; -			// Children were added by addChild() which uses push_front to insert them into list, -			// so to get buttons in correct order reverse iterator is used (EXT-5906)  -			for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++) -			{ -				LLButton * button = dynamic_cast<LLButton*> (*it); -				if (button != NULL) -				{ -					button->setOrigin( offset, -							button->getRect().mBottom); -					button->setLeftHPad(2 * HPAD); -					button->setRightHPad(2 * HPAD); -					// set zero width before perform autoResize() -					button->setRect(LLRect(button->getRect().mLeft, -							button->getRect().mTop, button->getRect().mLeft, -							button->getRect().mBottom)); -					button->setAutoResize(true); -					button->autoResize(); -					offset += HPAD + button->getRect().getWidth(); -					button->setFollowsNone(); -				} -			} +					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor);  			//Prepare the rect for the view  			LLRect target_rect = mEditor->getDocumentView()->getRect(); @@ -924,6 +946,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  			mEditor->appendWidget(params, "\n", false);  		}  	} + +	// usual messages showing  	else  	{  		std::string message = irc_me ? chat.mText.substr(3) : chat.mText; @@ -931,7 +955,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		//MESSAGE TEXT PROCESSING  		//*HACK getting rid of redundant sender names in system notifications sent using sender name (see EXT-5010) -		if (use_plain_text_chat_history && gAgentID != chat.mFromID && chat.mFromID.notNull()) +		if (use_plain_text_chat_history && !from_me && chat.mFromID.notNull())  		{  			std::string slurl_about = SLURL_APP_AGENT + chat.mFromID.asString() + SLURL_ABOUT;  			if (message.length() > slurl_about.length() &&  @@ -946,13 +970,19 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  			message = chat.mFromName + message;  		} -		mEditor->appendText(message, FALSE, style_params); +		if (square_brackets) +		{ +			message += "]"; +	} + +		mEditor->appendText(message, prependNewLineState, body_message_params); +		prependNewLineState = false;  	}  	mEditor->blockUndo();  	// automatically scroll to end when receiving chat from myself -	if (chat.mFromID == gAgentID) +	if (from_me)  	{  		mEditor->setCursorAndScrollToEnd();  	} diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 9a84280f25..61772b4bb7 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -35,7 +35,7 @@  #include "llfloaterreg.h"  #include "lllocalcliprect.h"  #include "lltrans.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llviewercontrol.h"  #include "llagentdata.h" @@ -96,8 +96,15 @@ void	LLNearbyChatToastPanel::reshape		(S32 width, S32 height, BOOL called_from_p  {  	LLPanel::reshape(width, height,called_from_parent); -	LLUICtrl* msg_text = getChild<LLUICtrl>("msg_text", false); -	LLUICtrl* icon = getChild<LLUICtrl>("avatar_icon", false); +	// reshape() may be called from LLView::initFromParams() before the children are created. +	// We call findChild() instead of getChild() here to avoid creating dummy controls. +	LLUICtrl* msg_text = findChild<LLUICtrl>("msg_text", false); +	LLUICtrl* icon = findChild<LLUICtrl>("avatar_icon", false); + +	if (!msg_text || !icon) +	{ +		return; +	}  	LLRect msg_text_rect = msg_text->getRect();  	LLRect avatar_rect = icon->getRect(); @@ -316,12 +323,12 @@ BOOL	LLNearbyChatToastPanel::handleMouseUp	(S32 x, S32 y, MASK mask)  			return TRUE;  		else  		{ -			LLNearbyChatBar::getInstance()->showHistory(); +			LLNearbyChat::getInstance()->showHistory();  			return FALSE;  		}  	} -	LLNearbyChatBar::getInstance()->showHistory(); +	LLNearbyChat::getInstance()->showHistory();  	return LLPanel::handleMouseUp(x,y,mask);  } @@ -355,6 +362,8 @@ BOOL	LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask)  }  void LLNearbyChatToastPanel::draw()  { +	LLPanel::draw(); +  	if(mIsDirty)  	{  		LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon", false); @@ -372,7 +381,6 @@ void LLNearbyChatToastPanel::draw()  		}  		mIsDirty = false;  	} -	LLToastPanelBase::draw();  } diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index 1d700dcede..89b0c4f37a 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -40,7 +40,7 @@ typedef enum e_show_item_header  	CHATITEMHEADER_SHOW_BOTH  } EShowItemHeader; -class LLNearbyChatToastPanel: public LLToastPanelBase +class LLNearbyChatToastPanel : public LLPanel  {  protected:          LLNearbyChatToastPanel() diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index a661808d1f..17181edffc 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -335,30 +335,15 @@ void LLIMWellChiclet::messageCountChanged(const LLSD& session_data)  /*               LLNotificationChiclet implementation                   */  /************************************************************************/  LLNotificationChiclet::LLNotificationChiclet(const Params& p) -: LLSysWellChiclet(p) -, mUreadSystemNotifications(0) +:	LLSysWellChiclet(p), +	mUreadSystemNotifications(0)  { -	// connect counter handlers to the signals -	connectCounterUpdatersToSignal("notify"); -	connectCounterUpdatersToSignal("groupnotify"); -	connectCounterUpdatersToSignal("offer"); - +	mNotificationChannel.reset(new ChicletNotificationChannel(this));  	// ensure that notification well window exists, to synchronously  	// handle toast add/delete events.  	LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);  } -void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) -{ -	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); -	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); -	if(n_handler) -	{ -		n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); -		n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); -	} -} -  void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)  {  	std::string action = user_data.asString(); @@ -407,6 +392,18 @@ void LLNotificationChiclet::setCounter(S32 counter)  	updateWidget(getCounter() == 0);  } + +bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) +{ +	if( !(notification->canLogToIM() && notification->hasFormElements()) +		&& (!notification->getPayload().has("give_inventory_notification") +			|| notification->getPayload()["give_inventory_notification"])) +	{ +		return true; +	} +	return false; +} +  //////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 19683492c2..f51d7b622c 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -34,6 +34,7 @@  #include "lloutputmonitorctrl.h"  #include "llgroupmgr.h"  #include "llimview.h" +#include "llnotifications.h"  class LLMenuGL;  class LLIMFloater; @@ -872,9 +873,10 @@ class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver  {  	friend class LLUICtrlFactory;  public: -	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} -	virtual void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } -	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {} +	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} +	/*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; +	/*virtual*/ void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } +	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {}  	~LLIMWellChiclet();  protected: @@ -911,11 +913,35 @@ protected:  class LLNotificationChiclet : public LLSysWellChiclet  { +	LOG_CLASS(LLNotificationChiclet); +	  	friend class LLUICtrlFactory;  public:  	struct Params : public LLInitParam::Block<Params, LLSysWellChiclet::Params>{};  protected: +	struct ChicletNotificationChannel : public LLNotificationChannel +	{ +		ChicletNotificationChannel(LLNotificationChiclet* chiclet)  +		:	LLNotificationChannel(LLNotificationChannel::Params().filter(filterNotification).name(chiclet->getSessionId().asString())), +			mChiclet(chiclet) +		{ +			// connect counter handlers to the signals +			connectToChannel("Group Notifications"); +			connectToChannel("Offer"); +			connectToChannel("Notifications"); +		} + +		static bool filterNotification(LLNotificationPtr notify); +		// connect counter updaters to the corresponding signals +		/*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); } +		/*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); } + +		LLNotificationChiclet* const mChiclet; +	}; + +	boost::scoped_ptr<ChicletNotificationChannel> mNotificationChannel; +  	LLNotificationChiclet(const Params& p);  	/** @@ -933,12 +959,6 @@ protected:  	 */  	/*virtual*/ void createMenu(); -	// connect counter updaters to the corresponding signals -	void connectCounterUpdatersToSignal(const std::string& notification_type); - -	// methods for updating a number of unread System notifications -	void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } -	void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); }  	/*virtual*/ void setCounter(S32 counter);  	S32 mUreadSystemNotifications;  }; diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index f1bc51fbe7..39f5d0b8f6 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -57,19 +57,11 @@ LLChicletBar::LLChicletBar(const LLSD&)  :	mChicletPanel(NULL),  	mToolbarStack(NULL)  { -	// Firstly add our self to IMSession observers, so we catch session events -	// before chiclets do that. -	LLIMMgr::getInstance()->addSessionObserver(this); -  	buildFromFile("panel_chiclet_bar.xml");  }  LLChicletBar::~LLChicletBar()  { -	if (!LLSingleton<LLIMMgr>::destroyed()) -	{ -		LLIMMgr::getInstance()->removeSessionObserver(this); -	}  }  LLIMChiclet* LLChicletBar::createIMChiclet(const LLUUID& session_id) @@ -102,6 +94,13 @@ void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& nam  	// no need to spawn chiclets for participants in P2P calls called through Avaline  	if (session->isP2P() && session->isOtherParticipantAvaline()) return; +	// Do not spawn chiclet when using the new multitab conversation UI +	if (LLIMConversation::isChatMultiTab()) +	{ +		LLIMFloater::addToHost(session_id); +		return; +	} +	  	if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;  	LLIMChiclet* chiclet = createIMChiclet(session_id); @@ -109,7 +108,7 @@ void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& nam  	{  		chiclet->setIMSessionName(name);  		chiclet->setOtherParticipantId(other_participant_id); -		 +  		LLIMFloater::onIMChicletCreated(session_id);  	} @@ -125,10 +124,12 @@ void LLChicletBar::sessionRemoved(const LLUUID& session_id)  	if(getChicletPanel())  	{  		// IM floater should be closed when session removed and associated chiclet closed -		LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -		if (iMfloater != NULL) +		LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); +		if (im_floater != NULL && !im_floater->getStartConferenceInSameFloater())  		{ -			iMfloater->closeFloater(); +			// Close the IM floater only if we are not planning to close the P2P chat +			// and start a new conference in the same floater. +			im_floater->closeFloater();  		}  		getChicletPanel()->removeChiclet(session_id); diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index 1427bf95e0..7d0d904810 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -50,9 +50,10 @@ public:  	LLChicletPanel*	getChicletPanel() { return mChicletPanel; }  	// LLIMSessionObserver observe triggers -	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); -	virtual void sessionRemoved(const LLUUID& session_id); -	void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); +	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	/*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; +	/*virtual*/ void sessionRemoved(const LLUUID& session_id); +	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);  	S32 getTotalUnreadIMCount(); diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp new file mode 100644 index 0000000000..486cea4064 --- /dev/null +++ b/indra/newview/llconversationlog.cpp @@ -0,0 +1,352 @@ +/** + * @file llconversationlog.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llconversationlog.h" +#include "lltrans.h" + +struct Conversation_params +{ +	Conversation_params(time_t time) +	:	mTime(time), +		mTimestamp(LLConversation::createTimestamp(time)) +	{} + +	time_t		mTime; +	std::string	mTimestamp; +	SessionType	mConversationType; +	std::string	mConversationName; +	std::string	mHistoryFileName; +	LLUUID		mSessionID; +	LLUUID		mParticipantID; +	bool		mIsVoice; +	bool		mHasOfflineIMs; +}; + +/************************************************************************/ +/*             LLConversation implementation                            */ +/************************************************************************/ + +LLConversation::LLConversation(const Conversation_params& params) +:	mTime(params.mTime), +	mTimestamp(params.mTimestamp), +	mConversationType(params.mConversationType), +	mConversationName(params.mConversationName), +	mHistoryFileName(params.mHistoryFileName), +	mSessionID(params.mSessionID), +	mParticipantID(params.mParticipantID), +	mIsVoice(params.mIsVoice), +	mHasOfflineIMs(params.mHasOfflineIMs) +{ +	setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLIMModel::LLIMSession& session) +:	mTime(time_corrected()), +	mTimestamp(createTimestamp(mTime)), +	mConversationType(session.mSessionType), +	mConversationName(session.mName), +	mHistoryFileName(session.mHistoryFileName), +	mSessionID(session.mSessionID), +	mParticipantID(session.mOtherParticipantID), +	mIsVoice(session.mStartedAsIMCall), +	mHasOfflineIMs(session.mHasOfflineMessage) +{ +	setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLConversation& conversation) +{ +	mTime				= conversation.getTime(); +	mTimestamp			= conversation.getTimestamp(); +	mConversationType	= conversation.getConversationType(); +	mConversationName	= conversation.getConversationName(); +	mHistoryFileName	= conversation.getHistoryFileName(); +	mSessionID			= conversation.getSessionID(); +	mParticipantID		= conversation.getParticipantID(); +	mIsVoice			= conversation.isVoice(); +	mHasOfflineIMs		= conversation.hasOfflineMessages(); + +	setListenIMFloaterOpened(); +} + +LLConversation::~LLConversation() +{ +	mIMFloaterShowedConnection.disconnect(); +} + +void LLConversation::onIMFloaterShown(const LLUUID& session_id) +{ +	if (mSessionID == session_id) +	{ +		mHasOfflineIMs = false; +	} +} + +// static +const std::string LLConversation::createTimestamp(const time_t& utc_time) +{ +	std::string timeStr; +	LLSD substitution; +	substitution["datetime"] = (S32) utc_time; + +	timeStr = "["+LLTrans::getString ("TimeMonth")+"]/[" +				 +LLTrans::getString ("TimeDay")+"]/[" +				 +LLTrans::getString ("TimeYear")+"] [" +				 +LLTrans::getString ("TimeHour")+"]:[" +				 +LLTrans::getString ("TimeMin")+"]"; + + +	LLStringUtil::format (timeStr, substitution); +	return timeStr; +} + +void LLConversation::setListenIMFloaterOpened() +{ +	LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); + +	bool has_offline_ims = !mIsVoice && mHasOfflineIMs; +	bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + +	// we don't need to listen for im floater with this conversation is opened +	// if floater is already opened or this conversation doesn't have unread offline messages +	if (has_offline_ims && !ims_are_read) +	{ +		mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); +	} +} +/************************************************************************/ +/*             LLConversationLogFriendObserver implementation           */ +/************************************************************************/ + +// Note : An LLSingleton like LLConversationLog cannot be an LLFriendObserver  +// at the same time. +// This is because avatar observers are deleted by the observed object which  +// conflicts with the way LLSingleton are deleted. + +class LLConversationLogFriendObserver : public LLFriendObserver +{ +public: +	LLConversationLogFriendObserver() {} +	virtual ~LLConversationLogFriendObserver() {} +	virtual void changed(U32 mask); +}; + +void LLConversationLogFriendObserver::changed(U32 mask) +{ +	if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) +	{ +		LLConversationLog::instance().notifyObservers(); +	} +} + +/************************************************************************/ +/*             LLConversationLog implementation                         */ +/************************************************************************/ + +LLConversationLog::LLConversationLog() +{ +	loadFromFile(getFileName()); + +	LLIMMgr::instance().addSessionObserver(this); +	 +	mFriendObserver = new LLConversationLogFriendObserver; +	LLAvatarTracker::instance().addObserver(mFriendObserver); +} +void LLConversationLog::logConversation(const LLConversation& conversation) +{ +	mConversations.push_back(conversation); +	notifyObservers(); +} + +void LLConversationLog::removeConversation(const LLConversation& conversation) +{ +	conversations_vec_t::iterator conv_it = mConversations.begin(); +	for(; conv_it != mConversations.end(); ++conv_it) +	{ +		if (conv_it->getSessionID() == conversation.getSessionID() && conv_it->getTime() == conversation.getTime()) +		{ +			mConversations.erase(conv_it); +			notifyObservers(); +			return; +		} +	} +} + +const LLConversation* LLConversationLog::getConversation(const LLUUID& session_id) +{ +	conversations_vec_t::const_iterator conv_it = mConversations.begin(); +	for(; conv_it != mConversations.end(); ++conv_it) +	{ +		if (conv_it->getSessionID() == session_id) +		{ +			return &*conv_it; +		} +	} + +	return NULL; +} + +void LLConversationLog::addObserver(LLConversationLogObserver* observer) +{ +	mObservers.insert(observer); +} + +void LLConversationLog::removeObserver(LLConversationLogObserver* observer) +{ +	mObservers.erase(observer); +} + +void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); +	if (session) +	{ +		LLConversation conversation(*session); +		LLConversationLog::instance().logConversation(conversation); +	} +} + +void LLConversationLog::cache() +{ +	saveToFile(getFileName()); +} + +std::string LLConversationLog::getFileName() +{ +	std::string filename = "conversation"; +	return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, filename) + ".log"; +} + +bool LLConversationLog::saveToFile(const std::string& filename) +{ +	if(!filename.size()) +	{ +		llwarns << "Call log list filename is empty!" << llendl; +		return false; +	} + +	LLFILE* fp = LLFile::fopen(filename, "wb"); +	if (!fp) +	{ +		llwarns << "Couldn't open call log list" << filename << llendl; +		return false; +	} + +	std::string participant_id; +	std::string conversation_id; + +	conversations_vec_t::const_iterator conv_it = mConversations.begin(); +	for (; conv_it != mConversations.end(); ++conv_it) +	{ +		conv_it->getSessionID().toString(conversation_id); +		conv_it->getParticipantID().toString(participant_id); + +		// examples of two file entries +		// [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe| +		// [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| + +		fprintf(fp, "[%d] %d %d %d %s| %s %s %s|\n", +				(S32)conv_it->getTime(), +				(S32)conv_it->getConversationType(), +				(S32)conv_it->isVoice(), +				(S32)conv_it->hasOfflineMessages(), +				     conv_it->getConversationName().c_str(), +				participant_id.c_str(), +				conversation_id.c_str(), +				conv_it->getHistoryFileName().c_str()); +	} +	fclose(fp); +	return true; +} +bool LLConversationLog::loadFromFile(const std::string& filename) +{ +	if(!filename.size()) +	{ +		llwarns << "Call log list filename is empty!" << llendl; +		return false; +	} + +	LLFILE* fp = LLFile::fopen(filename, "rb"); +	if (!fp) +	{ +		llwarns << "Couldn't open call log list" << filename << llendl; +		return false; +	} + +	char buffer[MAX_STRING]; +	char conv_name_buffer[MAX_STRING]; +	char part_id_buffer[MAX_STRING]; +	char conv_id_buffer[MAX_STRING]; +	char history_file_name[MAX_STRING]; +	int is_voice; +	int has_offline_ims; +	int stype; +	S32 time; + +	while (!feof(fp) && fgets(buffer, MAX_STRING, fp)) +	{ +		conv_name_buffer[0] = '\0'; +		part_id_buffer[0]	= '\0'; +		conv_id_buffer[0]	= '\0'; + +		sscanf(buffer, "[%d] %d %d %d %[^|]| %s %s %[^|]|", +				&time, +				&stype, +				&is_voice, +				&has_offline_ims, +				conv_name_buffer, +				part_id_buffer, +				conv_id_buffer, +				history_file_name); + +		Conversation_params params(time); +		params.mConversationType = (SessionType)stype; +		params.mIsVoice = is_voice; +		params.mHasOfflineIMs = has_offline_ims; +		params.mConversationName = std::string(conv_name_buffer); +		params.mParticipantID = LLUUID(part_id_buffer); +		params.mSessionID = LLUUID(conv_id_buffer); +		params.mHistoryFileName = std::string(history_file_name); + +		LLConversation conversation(params); +		mConversations.push_back(conversation); +	} +	fclose(fp); + +	notifyObservers(); +	return true; +} + +void LLConversationLog::notifyObservers() +{ +	std::set<LLConversationLogObserver*>::const_iterator iter = mObservers.begin(); +	for (; iter != mObservers.end(); ++iter) +	{ +		(*iter)->changed(); +	} +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h new file mode 100644 index 0000000000..a7457d55e3 --- /dev/null +++ b/indra/newview/llconversationlog.h @@ -0,0 +1,165 @@ +/** + * @file llconversationlog.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLCONVERSATIONLOG_H_ +#define LLCONVERSATIONLOG_H_ + +#include "llcallingcard.h" +#include "llimfloater.h" +#include "llimview.h" + +class LLConversationLogObserver; +struct Conversation_params; + +typedef LLIMModel::LLIMSession::SType SessionType; + +/* + * This class represents a particular session(conversation) of any type(im/voice/p2p/group/...) by storing some of session's data. + * Each LLConversation object has a corresponding visual representation in a form of LLConversationLogListItem. + */ +class LLConversation +{ +public: + +	LLConversation(const Conversation_params& params); +	LLConversation(const LLIMModel::LLIMSession& session); +	LLConversation(const LLConversation& conversation); + +	~LLConversation(); + +	const SessionType&	getConversationType()	const	{ return mConversationType; } +	const std::string&	getConversationName()	const	{ return mConversationName; } +	const std::string&	getHistoryFileName()	const	{ return mHistoryFileName; } +	const LLUUID&		getSessionID()			const	{ return mSessionID; } +	const LLUUID&		getParticipantID()		const	{ return mParticipantID; } +	const std::string&	getTimestamp()			const	{ return mTimestamp; } +	const time_t&		getTime()				const	{ return mTime; } +	bool				isVoice()				const	{ return mIsVoice; } +	bool				hasOfflineMessages()	const	{ return mHasOfflineIMs; } + +	/* +	 * Resets flag of unread offline message to false when im floater with this conversation is opened. +	 */ +	void onIMFloaterShown(const LLUUID& session_id); + +	/* +	 * returns string representation(in form of: mm/dd/yyyy hh:mm) of time when conversation was started +	 */ +	static const std::string createTimestamp(const time_t& utc_time); + +private: + +	/* +	 * If conversation has unread offline messages sets callback for opening LLIMFloater +	 * with this conversation. +	 */ +	void setListenIMFloaterOpened(); + +	boost::signals2::connection mIMFloaterShowedConnection; + +	time_t			mTime; // start time of conversation +	SessionType		mConversationType; +	std::string		mConversationName; +	std::string		mHistoryFileName; +	LLUUID			mSessionID; +	LLUUID			mParticipantID; +	bool			mIsVoice; +	bool			mHasOfflineIMs; +	std::string		mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm +}; + +/** + * LLConversationLog stores all agent's conversations. + * This class is responsible for creating and storing LLConversation objects when im or voice session starts. + * Also this class saves/retrieves conversations to/from file. + * + * Also please note that it may be several conversations with the same sessionID stored in the conversation log. + * To distinguish two conversations with the same sessionID it's also needed to compare their creation date. + */ + +class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObserver +{ +	friend class LLSingleton<LLConversationLog>; +public: + +	/** +	 * adds conversation to the conversation list and notifies observers +	 */ +	void logConversation(const LLConversation& conversation); +	void removeConversation(const LLConversation& conversation); + +	/** +	 * Returns first conversation with matched session_id +	 */ +	const LLConversation* getConversation(const LLUUID& session_id); + +	void addObserver(LLConversationLogObserver* observer); +	void removeObserver(LLConversationLogObserver* observer); + +	const std::vector<LLConversation>& getConversations() { return mConversations; } + +	// LLIMSessionObserver triggers +	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}							// Stub +	virtual void sessionRemoved(const LLUUID& session_id){}										// Stub +	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}	// Stub + +	// Triggered by LLFriendObserver change +	void notifyObservers(); + +	/** +	 * public method which is called on viewer exit to save conversation log +	 */ +	void cache(); + +private: + +	LLConversationLog(); + +	/** +	 * constructs file name in which conversations log will be saved +	 * file name template: agentID.call_log. +	 * For example: a086icaa-782d-88d0-ae29-987a55c99sss.call_log +	 */ +	std::string getFileName(); + +	bool saveToFile(const std::string& filename); +	bool loadFromFile(const std::string& filename); + +	typedef std::vector<LLConversation> conversations_vec_t; +	std::vector<LLConversation>				mConversations; +	std::set<LLConversationLogObserver*>	mObservers; + +	LLFriendObserver* mFriendObserver;		// Observer of the LLAvatarTracker instance +}; + +class LLConversationLogObserver +{ +public: +	virtual ~LLConversationLogObserver(){} +	virtual void changed() = 0; +}; + +#endif /* LLCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp new file mode 100644 index 0000000000..257ec082a5 --- /dev/null +++ b/indra/newview/llconversationloglist.cpp @@ -0,0 +1,422 @@ +/** + * @file llconversationloglist.cpp + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llavataractions.h" +#include "llagent.h" +#include "llfloaterreg.h" +#include "llfloaterconversationpreview.h" +#include "llgroupactions.h" +#include "llconversationloglist.h" +#include "llconversationloglistitem.h" +#include "llviewermenu.h" + +static LLDefaultChildRegistry::Register<LLConversationLogList> r("conversation_log_list"); + +static LLConversationLogListNameComparator NAME_COMPARATOR; +static LLConversationLogListDateComparator DATE_COMPARATOR; + +LLConversationLogList::LLConversationLogList(const Params& p) +:	LLFlatListViewEx(p), +	mIsDirty(true) +{ +	LLConversationLog::instance().addObserver(this); + +	// Set up context menu. +	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar check_registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + +	registrar.add		("Calllog.Action",	boost::bind(&LLConversationLogList::onCustomAction,	this, _2)); +	check_registrar.add ("Calllog.Check",	boost::bind(&LLConversationLogList::isActionChecked,this, _2)); +	enable_registrar.add("Calllog.Enable",	boost::bind(&LLConversationLogList::isActionEnabled,this, _2)); + +	LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( +									"menu_conversation_log_gear.xml", +									gMenuHolder, +									LLViewerMenuHolderGL::child_registry_t::instance()); +	if(context_menu) +	{ +		mContextMenu = context_menu->getHandle(); +	} + +	mIsFriendsOnTop = gSavedSettings.getBOOL("SortFriendsFirst"); +} + +LLConversationLogList::~LLConversationLogList() +{ +	if (mContextMenu.get()) +	{ +		mContextMenu.get()->die(); +	} + +	LLConversationLog::instance().removeObserver(this); +} + +void LLConversationLogList::draw() +{ +	if (mIsDirty) +	{ +		refresh(); +	} +	LLFlatListViewEx::draw(); +} + +BOOL LLConversationLogList::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ +	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); + +	LLToggleableMenu* context_menu = mContextMenu.get(); +	{ +		context_menu->buildDrawLabels(); +	if (context_menu && size()) +		context_menu->updateParent(LLMenuGL::sMenuContainer); +		LLMenuGL::showPopup(this, context_menu, x, y); +	} + +	return handled; +} + +void LLConversationLogList::setNameFilter(const std::string& filter) +{ +	std::string filter_upper = filter; +	LLStringUtil::toUpper(filter_upper); +	if (mNameFilter != filter_upper) +	{ +		mNameFilter = filter_upper; +		setDirty(); +	} +} + +bool LLConversationLogList::findInsensitive(std::string haystack, const std::string& needle_upper) +{ +    LLStringUtil::toUpper(haystack); +    return haystack.find(needle_upper) != std::string::npos; +} + +void LLConversationLogList::sortByName() +{ +	setComparator(&NAME_COMPARATOR); +	sort(); +} + +void LLConversationLogList::sortByDate() +{ +	setComparator(&DATE_COMPARATOR); +	sort(); +} + +void LLConversationLogList::toggleSortFriendsOnTop() +{ +	mIsFriendsOnTop = !mIsFriendsOnTop; +	gSavedSettings.setBOOL("SortFriendsFirst", mIsFriendsOnTop); +	sort(); +} + +void LLConversationLogList::changed() +{ +	refresh(); +} + +void LLConversationLogList::addNewItem(const LLConversation* conversation) +{ +	LLConversationLogListItem* item = new LLConversationLogListItem(&*conversation); +	if (!mNameFilter.empty()) +	{ +		item->highlightNameDate(mNameFilter); +	} +	addItem(item, conversation->getSessionID(), ADD_TOP); +} + +void LLConversationLogList::refresh() +{ +	rebuildList(); +	sort(); + +	mIsDirty = false; +} + +void LLConversationLogList::rebuildList() +{ +	clear(); + +	bool have_filter = !mNameFilter.empty(); + +	const std::vector<LLConversation>& conversations = LLConversationLog::instance().getConversations(); +	std::vector<LLConversation>::const_iterator iter = conversations.begin(); + +	for (; iter != conversations.end(); ++iter) +	{ +		bool not_found = have_filter && !findInsensitive(iter->getConversationName(), mNameFilter) && !findInsensitive(iter->getTimestamp(), mNameFilter); +		if (not_found) +			continue; + +		addNewItem(&*iter); +	} +} + +void LLConversationLogList::onCustomAction(const LLSD& userdata) +{ +	const std::string command_name = userdata.asString(); +	const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); +	LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); + +	if ("im" == command_name) +	{ +		switch (stype) +		{ +		case LLIMModel::LLIMSession::P2P_SESSION: +			LLAvatarActions::startIM(selected_id); +			break; + +		case LLIMModel::LLIMSession::GROUP_SESSION: +			LLGroupActions::startIM(getSelectedConversation()->getSessionID()); +			break; + +		default: +			break; +		} +	} +	else if ("call" == command_name) +	{ +		switch (stype) +		{ +		case LLIMModel::LLIMSession::P2P_SESSION: +			LLAvatarActions::startCall(selected_id); +			break; + +		case LLIMModel::LLIMSession::GROUP_SESSION: +			LLGroupActions::startCall(getSelectedConversation()->getSessionID()); +			break; + +		default: +			break; +		} +	} +	else if ("view_profile" == command_name) +	{ +		switch (stype) +		{ +		case LLIMModel::LLIMSession::P2P_SESSION: +			LLAvatarActions::showProfile(selected_id); +			break; + +		case LLIMModel::LLIMSession::GROUP_SESSION: +			LLGroupActions::show(getSelectedConversation()->getSessionID()); +			break; + +		default: +			break; +		} +	} +	else if ("chat_history" == command_name) +	{ +		const LLUUID& session_id = getSelectedConversation()->getSessionID(); +		LLFloaterReg::showInstance("preview_conversation", session_id, true); +	} +	else if ("offer_teleport" == command_name) +	{ +		LLAvatarActions::offerTeleport(selected_id); +	} +	else if("add_rem_friend" == command_name) +	{ +		if (LLAvatarActions::isFriend(selected_id)) +		{ +			LLAvatarActions::removeFriendDialog(selected_id); +		} +		else +		{ +			LLAvatarActions::requestFriendshipDialog(selected_id); +		} +	} +	else if ("invite_to_group" == command_name) +	{ +		LLAvatarActions::inviteToGroup(selected_id); +	} +	else if ("show_on_map" == command_name) +	{ +		LLAvatarActions::showOnMap(selected_id); +	} +	else if ("share" == command_name) +	{ +		LLAvatarActions::share(selected_id); +	} +	else if ("pay" == command_name) +	{ +		LLAvatarActions::pay(selected_id); +	} +	else if ("block" == command_name) +	{ +		LLAvatarActions::toggleBlock(selected_id); +	} +} + +bool LLConversationLogList::isActionEnabled(const LLSD& userdata) +{ +	if (numSelected() != 1) +	{ +		return false; +	} + +	const std::string command_name = userdata.asString(); + +	LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); +	const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + +	bool is_p2p   = LLIMModel::LLIMSession::P2P_SESSION == stype; +	bool is_group = LLIMModel::LLIMSession::GROUP_SESSION == stype; + +	if ("can_im" == command_name || "can_view_profile" == command_name) +	{ +		return is_p2p || is_group; +	} +	else if ("can_view_chat_history" == command_name) +	{ +		return true; +	} +	else if ("can_call"	== command_name) +	{ +		return (is_p2p || is_group) && LLAvatarActions::canCall(); +	} +	else if ("add_rem_friend"		== command_name || +			 "can_invite_to_group"	== command_name || +			 "can_share"			== command_name || +			 "can_block"			== command_name || +			 "can_pay"				== command_name) +	{ +		return is_p2p; +	} +	else if("can_offer_teleport" == command_name) +	{ +		return is_p2p && LLAvatarActions::canOfferTeleport(selected_id); +	} +	else if ("can_show_on_map") +	{ +		return is_p2p && ((LLAvatarTracker::instance().isBuddyOnline(selected_id) && is_agent_mappable(selected_id)) || gAgent.isGodlike()); +	} + +	return false; +} + +bool LLConversationLogList::isActionChecked(const LLSD& userdata) +{ +	const std::string command_name = userdata.asString(); + +	const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); +	bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == getSelectedSessionType(); + +	if ("is_blocked" == command_name) +	{ +		return is_p2p && LLAvatarActions::isBlocked(selected_id); +	} +	else if ("is_friend" == command_name) +	{ +		return is_p2p && LLAvatarActions::isFriend(selected_id); +	} + +	return false; +} + +LLIMModel::LLIMSession::SType LLConversationLogList::getSelectedSessionType() +{ +	const LLConversationLogListItem* item = getSelectedConversationPanel(); + +	if (item) +	{ +		return item->getConversation()->getConversationType(); +	} + +	return LLIMModel::LLIMSession::NONE_SESSION; +} + +const LLConversationLogListItem* LLConversationLogList::getSelectedConversationPanel() +{ +	LLPanel* panel = LLFlatListViewEx::getSelectedItem(); +	LLConversationLogListItem* conv_panel = dynamic_cast<LLConversationLogListItem*>(panel); + +	return conv_panel; +} + +const LLConversation* LLConversationLogList::getSelectedConversation() +{ +	const LLConversationLogListItem* panel = getSelectedConversationPanel(); + +	if (panel) +	{ +		return panel->getConversation(); +	} + +	return NULL; +} + +bool LLConversationLogListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const +{ +	const LLConversationLogListItem* conversation_item1 = dynamic_cast<const LLConversationLogListItem*>(item1); +	const LLConversationLogListItem* conversation_item2 = dynamic_cast<const LLConversationLogListItem*>(item2); + +	if (!conversation_item1 || !conversation_item2) +	{ +		llerror("conversation_item1 and conversation_item2 cannot be null", 0); +		return true; +	} + +	return doCompare(conversation_item1, conversation_item2); +} + +bool LLConversationLogListNameComparator::doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const +{ +	std::string name1 = conversation1->getConversation()->getConversationName(); +	std::string name2 = conversation2->getConversation()->getConversationName(); +	const LLUUID& id1 = conversation1->getConversation()->getParticipantID(); +	const LLUUID& id2 = conversation2->getConversation()->getParticipantID(); + +	LLStringUtil::toUpper(name1); +	LLStringUtil::toUpper(name2); + +	bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); +	if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) +	{ +		return LLAvatarActions::isFriend(id1); +	} + +	return name1 < name2; +} + +bool LLConversationLogListDateComparator::doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const +{ +	time_t date1 = conversation1->getConversation()->getTime(); +	time_t date2 = conversation2->getConversation()->getTime(); +	const LLUUID& id1 = conversation1->getConversation()->getParticipantID(); +	const LLUUID& id2 = conversation2->getConversation()->getParticipantID(); + +	bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); +	if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) +	{ +		return LLAvatarActions::isFriend(id1); +	} + +	return date1 > date2; +} diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h new file mode 100644 index 0000000000..dff34a74c6 --- /dev/null +++ b/indra/newview/llconversationloglist.h @@ -0,0 +1,143 @@ +/** + * @file llconversationloglist.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLCONVERSATIONLOGLIST_H_ +#define LLCONVERSATIONLOGLIST_H_ + +#include "llconversationlog.h" +#include "llflatlistview.h" +#include "lltoggleablemenu.h" + +class LLConversationLogListItem; + +/** + * List of all agent's conversations. I.e. history of conversations. + * This list represents contents of the LLConversationLog. + * Each change in LLConversationLog leads to rebuilding this list, so + * it's always in actual state. + */ + +class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogObserver +{ +	LOG_CLASS(LLConversationLogList); +public: +	struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> +	{ +		Params(){}; +	}; + +	LLConversationLogList(const Params& p); +	virtual ~LLConversationLogList(); + +	virtual void draw(); + +	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + +	LLToggleableMenu*	getContextMenu() const { return mContextMenu.get(); } + +	void addNewItem(const LLConversation* conversation); +	void setNameFilter(const std::string& filter); +	void sortByName(); +	void sortByDate(); +	void toggleSortFriendsOnTop(); +	bool getSortFriendsOnTop() const { return mIsFriendsOnTop; } + +	/** +	 * Changes from LLConversationLogObserver +	 */ +	virtual void changed(); + +private: + +	void setDirty(bool dirty = true) { mIsDirty = dirty; } +	void refresh(); + +	/** +	 * Clears list and re-adds items from LLConverstationLog +	 * If filter is not empty re-adds items which match the filter +	 */ +	void rebuildList(); + +	bool findInsensitive(std::string haystack, const std::string& needle_upper); + +	void onCustomAction (const LLSD& userdata); +	bool isActionEnabled(const LLSD& userdata); +	bool isActionChecked(const LLSD& userdata); + +	LLIMModel::LLIMSession::SType getSelectedSessionType(); +	const LLConversationLogListItem* getSelectedConversationPanel(); +	const LLConversation* getSelectedConversation(); + +	LLHandle<LLToggleableMenu>	mContextMenu; +	bool mIsDirty; +	bool mIsFriendsOnTop; +	std::string mNameFilter; +}; + +/** + * Abstract comparator for ConversationLogList items + */ +class LLConversationLogListItemComparator : public LLFlatListView::ItemComparator +{ +	LOG_CLASS(LLConversationLogListItemComparator); + +public: +	LLConversationLogListItemComparator() {}; +	virtual ~LLConversationLogListItemComparator() {}; + +	virtual bool compare(const LLPanel* item1, const LLPanel* item2) const; + +protected: + +	virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const = 0; +}; + +class LLConversationLogListNameComparator : public LLConversationLogListItemComparator +{ +	LOG_CLASS(LLConversationLogListNameComparator); + +public: +	LLConversationLogListNameComparator() {}; +	virtual ~LLConversationLogListNameComparator() {}; + +protected: + +	virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const; +}; + +class LLConversationLogListDateComparator : public LLConversationLogListItemComparator +{ +	LOG_CLASS(LLConversationLogListDateComparator); + +public: +	LLConversationLogListDateComparator() {}; +	virtual ~LLConversationLogListDateComparator() {}; + +protected: + +	virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const; +}; + +#endif /* LLCONVERSATIONLOGLIST_H_ */ diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp new file mode 100644 index 0000000000..dddf216592 --- /dev/null +++ b/indra/newview/llconversationloglistitem.cpp @@ -0,0 +1,177 @@ +/** + * @file llconversationloglistitem.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +// llui +#include "lliconctrl.h" +#include "lltextbox.h" +#include "lltextutil.h" + +// newview +#include "llavataractions.h" +#include "llavatariconctrl.h" +#include "llconversationlog.h" +#include "llconversationloglistitem.h" +#include "llgroupactions.h" +#include "llgroupiconctrl.h" +#include "llinventoryicon.h" + +LLConversationLogListItem::LLConversationLogListItem(const LLConversation* conversation) +:	LLPanel(), +	mConversation(conversation), +	mConversationName(NULL), +	mConversationDate(NULL) +{ +	buildFromFile("panel_conversation_log_list_item.xml"); + +	LLIMFloater* floater = LLIMFloater::findInstance(mConversation->getSessionID()); + +	bool has_offline_ims = !mConversation->isVoice() && mConversation->hasOfflineMessages(); +	bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + +	if (has_offline_ims && !ims_are_read) +	{ +		mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversationLogListItem::onIMFloaterShown, this, _1)); +	} +} + +LLConversationLogListItem::~LLConversationLogListItem() +{ +	mIMFloaterShowedConnection.disconnect(); +} + +BOOL LLConversationLogListItem::postBuild() +{ +	initIcons(); + +	// set conversation name +	mConversationName = getChild<LLTextBox>("conversation_name"); +	mConversationName->setValue(mConversation->getConversationName()); + +	// set conversation date and time +	mConversationDate = getChild<LLTextBox>("date_time"); +	mConversationDate->setValue(mConversation->getTimestamp()); + +	getChild<LLButton>("delete_btn")->setClickedCallback(boost::bind(&LLConversationLogListItem::onRemoveBtnClicked, this)); +	setDoubleClickCallback(boost::bind(&LLConversationLogListItem::onDoubleClick, this)); + +	return TRUE; +} + +void LLConversationLogListItem::initIcons() +{ +	switch (mConversation->getConversationType()) +	{ +		case LLIMModel::LLIMSession::P2P_SESSION: +		case LLIMModel::LLIMSession::ADHOC_SESSION: +		{ +			LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); +			avatar_icon->setVisible(TRUE); +			avatar_icon->setValue(mConversation->getParticipantID()); +			break; +		} +		case LLIMModel::LLIMSession::GROUP_SESSION: +		{ +			LLGroupIconCtrl* group_icon = getChild<LLGroupIconCtrl>("group_icon"); +			group_icon->setVisible(TRUE); +			group_icon->setValue(mConversation->getSessionID()); +			break; +		} +		default: +			break; +	} + +	if (mConversation->isVoice()) +	{ +		getChild<LLIconCtrl>("voice_session_icon")->setVisible(TRUE); +	} +	else +	{ +		if (mConversation->hasOfflineMessages()) +		{ +			getChild<LLIconCtrl>("unread_ims_icon")->setVisible(TRUE); +		} +	} +} + +void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ +	getChildView("hovered_icon")->setVisible(true); +	LLPanel::onMouseEnter(x, y, mask); +} + +void LLConversationLogListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ +	getChildView("hovered_icon")->setVisible(false); +	LLPanel::onMouseLeave(x, y, mask); +} + +void LLConversationLogListItem::setValue(const LLSD& value) +{ +	if (!value.isMap() || !value.has("selected")) +	{ +		return; +	} + +	getChildView("selected_icon")->setVisible(value["selected"]); +} + +void LLConversationLogListItem::onIMFloaterShown(const LLUUID& session_id) +{ +	if (mConversation->getSessionID() == session_id) +	{ +		getChild<LLIconCtrl>("unread_ims_icon")->setVisible(FALSE); +	} +} + +void LLConversationLogListItem::onRemoveBtnClicked() +{ +	LLConversationLog::instance().removeConversation(*mConversation); +} + +void LLConversationLogListItem::highlightNameDate(const std::string& highlited_text) +{ +	LLStyle::Params params; +	LLTextUtil::textboxSetHighlightedVal(mConversationName, params, mConversation->getConversationName(), highlited_text); +	LLTextUtil::textboxSetHighlightedVal(mConversationDate, params, mConversation->getTimestamp(), highlited_text); +} + +void LLConversationLogListItem::onDoubleClick() +{ +	switch (mConversation->getConversationType()) +	{ +	case LLIMModel::LLIMSession::P2P_SESSION: +		LLAvatarActions::startIM(mConversation->getParticipantID()); +		break; + +	case LLIMModel::LLIMSession::GROUP_SESSION: +		LLGroupActions::startIM(mConversation->getSessionID()); +		break; + +	default: +		break; +	} +} diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h new file mode 100644 index 0000000000..8943e11604 --- /dev/null +++ b/indra/newview/llconversationloglistitem.h @@ -0,0 +1,79 @@ +/** + * @file llconversationloglistitem.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLCONVERSATIONLOGLISTITEM_H_ +#define LLCONVERSATIONLOGLISTITEM_H_ + +#include "llimfloater.h" +#include "llpanel.h" + +class LLTextBox; +class LLConversation; + +/** + * This class is a visual representation of LLConversation, each of which is LLConversationLog entry. + * LLConversationLogList consists of these LLConversationLogListItems. + * LLConversationLogListItem consists of: + *		conversaion_type_icon + *		conversaion_name + *		conversaion_date + * Also LLConversationLogListItem holds pointer to its LLConversationLog. + */ + +class LLConversationLogListItem : public LLPanel +{ +public: +	LLConversationLogListItem(const LLConversation* conversation); +	virtual ~LLConversationLogListItem(); + +	void onMouseEnter(S32 x, S32 y, MASK mask); +	void onMouseLeave(S32 x, S32 y, MASK mask); + +	virtual void setValue(const LLSD& value); + +	virtual BOOL postBuild(); + +	void onIMFloaterShown(const LLUUID& session_id); +	void onRemoveBtnClicked(); + +	const LLConversation* getConversation() const { return mConversation; } + +	void highlightNameDate(const std::string& highlited_text); + +	void onDoubleClick(); + +private: + +	void initIcons(); + +	const LLConversation* mConversation; + +	LLTextBox*		mConversationName; +	LLTextBox*		mConversationDate; + +	boost::signals2::connection mIMFloaterShowedConnection; +}; + +#endif /* LLCONVERSATIONLOGITEM_H_ */ diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp new file mode 100644 index 0000000000..832dc3c3e4 --- /dev/null +++ b/indra/newview/llconversationmodel.cpp @@ -0,0 +1,76 @@ +/**  + * @file llconversationmodel.cpp + * @brief Implementation of conversations list + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llconversationmodel.h" + +// Conversation items +LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : +	LLFolderViewModelItemCommon(root_view_model), +	mName(display_name), +	mUUID(uuid) +{ +} + +LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_model) : +	LLFolderViewModelItemCommon(root_view_model), +	mName(""), +	mUUID() +{ +} + +// Virtual action callbacks +void LLConversationItem::performAction(LLInventoryModel* model, std::string action) +{ +} + +void LLConversationItem::openItem( void ) +{ +} + +void LLConversationItem::closeItem( void ) +{ +} + +void LLConversationItem::previewItem( void ) +{ +} + +void LLConversationItem::showProperties(void) +{ +} + +bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const +{ +	// We compare only by name for the moment +	// *TODO : Implement the sorting by date +	S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); +	return (compare < 0); +} + +// EOF diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h new file mode 100644 index 0000000000..cb03128cac --- /dev/null +++ b/indra/newview/llconversationmodel.h @@ -0,0 +1,188 @@ +/**  + * @file llconversationmodel.h + * @brief Implementation of conversations list + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLCONVERSATIONMODEL_H +#define LL_LLCONVERSATIONMODEL_H + +#include "llfolderviewitem.h" +#include "llfolderviewmodel.h" + +// Implementation of conversations list + +class LLConversationItem; + +typedef std::map<LLUUID, LLConversationItem*> conversations_items_map; +typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; + +// Conversation items: we hold a list of those and create an LLFolderViewItem widget for each   +// that we tuck into the mConversationsListPanel.  +class LLConversationItem : public LLFolderViewModelItemCommon +{ +public: +	LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); +	LLConversationItem(LLFolderViewModelInterface& root_view_model); +	virtual ~LLConversationItem() {} + +	// Stub those things we won't really be using in this conversation context +	virtual const std::string& getName() const { return mName; } +	virtual const std::string& getDisplayName() const { return mName; } +	virtual const std::string& getSearchableName() const { return mName; } +	virtual const LLUUID& getUUID() const { return mUUID; } +	virtual time_t getCreationDate() const { return 0; } +	virtual LLPointer<LLUIImage> getIcon() const { return NULL; } +	virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } +	virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } +	virtual std::string getLabelSuffix() const { return LLStringUtil::null; } +	virtual BOOL isItemRenameable() const { return FALSE; } +	virtual BOOL renameItem(const std::string& new_name) { return FALSE; } +	virtual BOOL isItemMovable( void ) const { return FALSE; } +	virtual BOOL isItemRemovable( void ) const { return FALSE; } +	virtual BOOL isItemInTrash( void) const { return FALSE; } +	virtual BOOL removeItem() { return FALSE; } +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) { } +	virtual void move( LLFolderViewModelItem* parent_listener ) { } +	virtual BOOL isItemCopyable() const { return FALSE; } +	virtual BOOL copyToClipboard() const { return FALSE; } +	virtual BOOL cutToClipboard() const { return FALSE; } +	virtual BOOL isClipboardPasteable() const { return FALSE; } +	virtual void pasteFromClipboard() { } +	virtual void pasteLinkFromClipboard() { } +	virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } +	virtual BOOL isUpToDate() const { return TRUE; } +	virtual bool hasChildren() const { return FALSE; } + +	virtual bool potentiallyVisible() { return true; } +	virtual bool filter( LLFolderViewFilter& filter) { return false; } +	virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } +	virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { } +	virtual bool passedFilter(S32 filter_generation = -1) { return true; } + +	// The action callbacks +	virtual void performAction(LLInventoryModel* model, std::string action); +	virtual void openItem( void ); +	virtual void closeItem( void ); +	virtual void previewItem( void ); +	virtual void selectItem(void) { }  +	virtual void showProperties(void); + +	// This method will be called to determine if a drop can be +	// performed, and will set drop to TRUE if a drop is +	// requested.  +	// Returns TRUE if a drop is possible/happened, FALSE otherwise. +	virtual BOOL dragOrDrop(MASK mask, BOOL drop, +							EDragAndDropType cargo_type, +							void* cargo_data, +							std::string& tooltip_msg) { return FALSE; } +	 +//	bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } +	bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } +private: +	std::string mName; +	const LLUUID mUUID; +}; + +// We don't want to ever filter conversations but we need to declare that class to create a conversation view model. +// We just stubb everything for the moment. +class LLConversationFilter : public LLFolderViewFilter +{ +public: +		 +	enum ESortOrderType +	{ +		SO_NAME = 0,						// Sort inventory by name +		SO_DATE = 0x1,						// Sort inventory by date +	}; + +	LLConversationFilter() { mEmpty = ""; } +	~LLConversationFilter() {} +		 +	bool 				check(const LLFolderViewModelItem* item) { return true; } +	bool				checkFolder(const LLFolderViewModelItem* folder) const { return true; } +	void 				setEmptyLookupMessage(const std::string& message) { } +	std::string			getEmptyLookupMessage() const { return mEmpty; } +	bool				showAllResults() const { return true; } +	std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const { return std::string::npos; } +	std::string::size_type getFilterStringSize() const { return 0; } +		 +	bool 				isActive() const { return false; } +	bool 				isModified() const { return false; } +	void 				clearModified() { } +	const std::string& 	getName() const { return mEmpty; } +	const std::string& 	getFilterText() { return mEmpty; } +	void 				setModified(EFilterModified behavior = FILTER_RESTART) { } +		 +	void 				setFilterCount(S32 count) { } +	S32 				getFilterCount() const { return 0; } +	void 				decrementFilterCount() { } +		 +	bool 				isDefault() const { return true; } +	bool 				isNotDefault() const { return false; } +	void 				markDefault() { } +	void 				resetDefault() { } +		 +	S32 				getCurrentGeneration() const { return 0; } +	S32 				getFirstSuccessGeneration() const { return 0; } +	S32 				getFirstRequiredGeneration() const { return 0; } +private: +	std::string mEmpty; +}; + +class LLConversationSort +{ +public: +	LLConversationSort(U32 order = 0) +	:	mSortOrder(order), +	mByDate(false), +	mByName(false) +	{ +		mByDate = (order & LLConversationFilter::SO_DATE); +		mByName = (order & LLConversationFilter::SO_NAME); +	} +	 +	bool isByDate() const { return mByDate; } +	U32 getSortOrder() const { return mSortOrder; } +	 +	bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const; +private: +	U32  mSortOrder; +	bool mByDate; +	bool mByName; +}; + +class LLConversationViewModel +:	public LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> +{ +public: +	typedef LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> base_t; +	 +	void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort +	bool contentsReady() { return true; }	// *TODO : we need to check that participants names are available somewhat +	bool startDrag(std::vector<LLFolderViewModelItem*>& items) { return false; } // We do not allow drag of conversation items +	 +private: +}; + +#endif // LL_LLCONVERSATIONMODEL_H diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp new file mode 100644 index 0000000000..6cc911ecef --- /dev/null +++ b/indra/newview/llconversationview.cpp @@ -0,0 +1,78 @@ +/**  + * @file llconversationview.cpp + * @brief Implementation of conversations list widgets and views + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llconversationview.h" +#include "llconversationmodel.h" +#include "llimconversation.h" +#include "llimfloatercontainer.h" + +LLConversationViewSession::Params::Params() :	 +	container() +{} + +LLConversationViewSession::LLConversationViewSession( const LLConversationViewSession::Params& p ): +	LLFolderViewFolder(p), +	mContainer(p.container) +{ +} + +void LLConversationViewSession::selectItem() +{ +	LLFolderViewItem::selectItem(); +	 +	LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); +	LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); +	LLMultiFloater* host_floater = session_floater->getHost(); +	 +	if (host_floater == mContainer) +	{ +		// Always expand the message pane if the panel is hosted by the container +		mContainer->collapseMessagesPane(false); +		// Switch to the conversation floater that is being selected +		mContainer->selectFloater(session_floater); +	} +	 +	// Set the focus on the selected floater +	session_floater->setFocus(TRUE); +} + +void LLConversationViewSession::setVisibleIfDetached(BOOL visible) +{ +	// Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized +	// Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here +	LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); +	LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); +	 +	if (session_floater && !session_floater->getHost() && !session_floater->isMinimized()) +	{ +		session_floater->setVisible(visible); +	} +} + +// EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h new file mode 100644 index 0000000000..6a51e719c8 --- /dev/null +++ b/indra/newview/llconversationview.h @@ -0,0 +1,58 @@ +/**  + * @file llconversationview.h + * @brief Implementation of conversations list widgets and views + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLCONVERSATIONVIEW_H +#define LL_LLCONVERSATIONVIEW_H + +#include "llfolderviewitem.h" + +class LLIMFloaterContainer; + +// Implementation of conversations list widgets + +class LLConversationViewSession : public LLFolderViewFolder +{ +public: +	struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params> +	{ +		Optional<LLIMFloaterContainer*>			container; + +		Params(); +	}; +		 +protected: +	friend class LLUICtrlFactory; +	LLConversationViewSession( const Params& p ); +	 +	LLIMFloaterContainer* mContainer; +	 +public: +	virtual ~LLConversationViewSession( void ) { } +	virtual void selectItem();	 +	void setVisibleIfDetached(BOOL visible); +}; + +#endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 89a2e9f407..4eda2b92b3 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -99,7 +99,6 @@ void LLDrawable::init()  	mPositionGroup.clear();  	mExtents[0].clear();  	mExtents[1].clear(); -	mQuietCount = 0;  	mState     = 0;  	mVObjp   = NULL; @@ -407,6 +406,8 @@ void LLDrawable::makeActive()  		if (!isRoot() && !mParent->isActive())  		{  			mParent->makeActive(); +			//NOTE: linked set will now NEVER become static +			mParent->setState(LLDrawable::ACTIVE_CHILD);  		}  		//all child objects must also be active @@ -426,41 +427,27 @@ void LLDrawable::makeActive()  		if (mVObjp->getPCode() == LL_PCODE_VOLUME)  		{ -			if (mVObjp->isFlexible()) -			{ -				return; -			} -		} -	 -		if (mVObjp->getPCode() == LL_PCODE_VOLUME) -		{  			gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE);  		}  		updatePartition();  	} -	if (isRoot()) -	{ -		mQuietCount = 0; -	} -	else -	{ -		getParent()->mQuietCount = 0; -	} +	llassert(isAvatar() || isRoot() || mParent->isActive());  }  void LLDrawable::makeStatic(BOOL warning_enabled)  { -	if (isState(ACTIVE)) +	if (isState(ACTIVE) &&  +		!isState(ACTIVE_CHILD) &&  +		!mVObjp->isAttachment() &&  +		!mVObjp->isFlexible())  	{  		clearState(ACTIVE | ANIMATED_CHILD); -		if (mParent.notNull() && mParent->isActive() && warning_enabled) -		{ -			LL_WARNS_ONCE("Drawable") << "Drawable becomes static with active parent!" << LL_ENDL; -		} - +		//drawable became static with active parent, not acceptable +		llassert(mParent.isNull() || !mParent->isActive() || !warning_enabled); +		  		LLViewerObject::const_child_list_t& child_list = mVObjp->getChildren();  		for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();  			 iter != child_list.end(); iter++) @@ -487,8 +474,8 @@ void LLDrawable::makeStatic(BOOL warning_enabled)  			mSpatialBridge->markDead();  			setSpatialBridge(NULL);  		} +		updatePartition();  	} -	updatePartition();  }  // Returns "distance" between target destination and resulting xfrom @@ -638,8 +625,6 @@ BOOL LLDrawable::updateMove()  		return FALSE;  	} -	makeActive(); -	  	BOOL done;  	if (isState(MOVE_UNDAMPED)) @@ -648,6 +633,7 @@ BOOL LLDrawable::updateMove()  	}  	else  	{ +		makeActive();  		done = updateMoveDamped();  	}  	return done; diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 960c64fa9e..b1e32bdb5b 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -292,6 +292,7 @@ public:  		RIGGED			= 0x08000000,  		PARTITION_MOVE	= 0x10000000,  		ANIMATED_CHILD  = 0x20000000, +		ACTIVE_CHILD	= 0x40000000,  	} EDrawableFlags;  private: //aligned members @@ -305,8 +306,6 @@ public:  	LLPointer<LLDrawable> mParent;  	F32				mDistanceWRTCamera; -	 -	S32				mQuietCount;  	static S32 getCurrentFrame() { return sCurVisible; }  	static S32 getMinVisFrameRange(); diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 013c698445..94dd927d26 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -419,6 +419,7 @@ void LLRenderPass::applyModelMatrix(LLDrawInfo& params)  		gGL.loadMatrix(gGLModelView);  		if (params.mModelMatrix)  		{ +			llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW);  			gGL.multMatrix((GLfloat*) params.mModelMatrix->mMatrix);  		}  		gPipeline.mMatrixOpCount++; diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 7fc78fb382..9bc32fddbd 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -308,6 +308,7 @@ void LLDrawPoolTerrain::drawLoop()  			if (model_matrix != gGLLastMatrix)  			{ +				llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW);  				gGLLastMatrix = model_matrix;  				gGL.loadMatrix(gGLModelView);  				if (model_matrix) @@ -594,7 +595,8 @@ void LLDrawPoolTerrain::renderFull4TU()  	gGL.matrixMode(LLRender::MM_TEXTURE);  	gGL.loadIdentity();  	gGL.translatef(-1.f, 0.f, 0.f); -   +	gGL.matrixMode(LLRender::MM_MODELVIEW); +  	// Set alpha texture and do lighting modulation  	gGL.getTexUnit(3)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_VERT_COLOR);  	gGL.getTexUnit(3)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); @@ -742,6 +744,7 @@ void LLDrawPoolTerrain::renderFull2TU()  	gGL.matrixMode(LLRender::MM_TEXTURE);  	gGL.loadIdentity();  	gGL.translatef(-1.f, 0.f, 0.f); +	gGL.matrixMode(LLRender::MM_MODELVIEW);  	// Care about alpha only  	gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); @@ -781,6 +784,7 @@ void LLDrawPoolTerrain::renderFull2TU()  	gGL.matrixMode(LLRender::MM_TEXTURE);  	gGL.loadIdentity();  	gGL.translatef(-2.f, 0.f, 0.f); +	gGL.matrixMode(LLRender::MM_MODELVIEW);  	// Care about alpha only  	gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 83f04e45a8..fedbd782dc 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -116,6 +116,7 @@ void LLDrawPoolTree::render(S32 pass)  				gGL.loadMatrix(gGLModelView);  				if (model_matrix)  				{ +					llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW);  					gGL.multMatrix((GLfloat*) model_matrix->mMatrix);  				}  				gPipeline.mMatrixOpCount++; diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index bf8338e5f2..fa42b157a7 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -129,7 +129,7 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth)  	llassert(mFullHeight <= 512);  	llassert(mFullWidth <= 512); -	if (gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete()) +	if (gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI)  	{ //using offscreen render target, just use the bottom left corner  		mOrigin.set(0, 0);  	} @@ -216,14 +216,12 @@ BOOL LLViewerDynamicTexture::updateAllInstances()  		return TRUE;  	} -#if 0 //THIS CAUSES MAINT-1092 -	bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete(); +	bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI;  	if (use_fbo)  	{  		gPipeline.mWaterDis.bindTarget();  	} -#endif  	LLGLSLShader::bindNoShader();  	LLVertexBuffer::unbind(); @@ -258,12 +256,10 @@ BOOL LLViewerDynamicTexture::updateAllInstances()  		}  	} -#if 0  	if (use_fbo)  	{  		gPipeline.mWaterDis.flush();  	} -#endif  	return ret;  } diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 935dcb74b0..a50184460b 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -150,7 +150,7 @@ void LLExpandableTextBox::LLTextBoxEx::showExpandText()  		std::pair<S32, S32> visible_lines = getVisibleLines(true);  		S32 last_line = visible_lines.second - 1; -		LLStyle::Params expander_style(getDefaultStyleParams()); +		LLStyle::Params expander_style(getStyleParams());  		expander_style.font.style = "UNDERLINE";  		expander_style.color = LLUIColorTable::instance().getColor("HTMLLinkColor");  		LLExpanderSegment* expanderp = new LLExpanderSegment(new LLStyle(expander_style), getLineStart(last_line), getLength() + 1, mExpanderLabel, *this); @@ -166,7 +166,7 @@ void LLExpandableTextBox::LLTextBoxEx::hideExpandText()  	if (mExpanderVisible)  	{  		// this will overwrite the expander segment and all text styling with a single style -		LLStyleConstSP sp(new LLStyle(getDefaultStyleParams())); +		LLStyleConstSP sp(new LLStyle(getStyleParams()));  		LLNormalTextSegment* segmentp = new LLNormalTextSegment(sp, 0, getLength() + 1, *this);  		insertSegment(segmentp); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 4cbc9cab4a..c68577db75 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -38,6 +38,7 @@  #include "lltooltip.h"  #include "llagent.h" +#include "llavatarnamecache.h"  #include "llclipboard.h"  #include "llclipboard.h"  #include "llinventorybridge.h" @@ -45,12 +46,14 @@  #include "llfloatersidepanelcontainer.h"  #include "llfloaterworldmap.h"  #include "lllandmarkactions.h" +#include "lllogininstance.h"  #include "llnotificationsutil.h"  #include "lltoggleablemenu.h"  #include "llviewerinventory.h"  #include "llviewermenu.h"  #include "llviewermenu.h"  #include "lltooldraganddrop.h" +#include "llsdserialize.h"  static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar"); @@ -317,7 +320,8 @@ public:  		if (item)  		{ -			item->setSortField(mSortField); +			LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField); +  			item->setComplete(TRUE);  			item->updateServer(FALSE); @@ -339,8 +343,8 @@ struct LLFavoritesSort  	// TODO - made it customizible using gSavedSettings  	bool operator()(const LLViewerInventoryItem* const& a, const LLViewerInventoryItem* const& b)  	{ -		S32 sortField1 = a->getSortField(); -		S32 sortField2 = b->getSortField(); +		S32 sortField1 = LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()); +		S32 sortField2 = LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID());  		if (!(sortField1 < 0 && sortField2 < 0))  		{ @@ -528,7 +532,7 @@ void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)  		mItems.push_back(gInventory.getItem(mDragItemId));  	} -	gInventory.saveItemsOrder(mItems); +	LLFavoritesOrderStorage::instance().saveItemsOrder(mItems);  	LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get(); @@ -587,7 +591,8 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con  		}  		else  		{ -			currItem->setSortField(++sortField); +			LLFavoritesOrderStorage::instance().setSortIndex(currItem, ++sortField); +  			currItem->setComplete(TRUE);  			currItem->updateServer(FALSE); @@ -640,7 +645,7 @@ void LLFavoritesBarCtrl::changed(U32 mask)  		for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)  		{ -			(*i)->getSLURL(); +			LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID());  		}  		updateButtons();  	} @@ -909,7 +914,7 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it  		S32 sortField = 0;  		for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)  		{ -			(*i)->setSortField(++sortField); +			LLFavoritesOrderStorage::instance().setSortIndex((*i), ++sortField);  		}  	} @@ -1355,7 +1360,7 @@ BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array  	// if there is an item without sort order field set, we need to save items order  	for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)  	{ -		if ((*i)->getSortField() < 0) +		if (LLFavoritesOrderStorage::instance().getSortIndex((*i)->getUUID()) < 0)  		{  			result = TRUE;  			break; @@ -1390,4 +1395,291 @@ void LLFavoritesBarCtrl::insertItem(LLInventoryModel::item_array_t& items, const  	}  } +const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; +const S32 LLFavoritesOrderStorage::NO_INDEX = -1; + +void LLFavoritesOrderStorage::setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index) +{ +	mSortIndexes[inv_item->getUUID()] = sort_index; +	mIsDirty = true; +	getSLURL(inv_item->getAssetUUID()); +} + +S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) +{ +	sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); +	if (it != mSortIndexes.end()) +	{ +		return it->second; +	} +	return NO_INDEX; +} + +void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) +{ +	mSortIndexes.erase(inv_item_id); +	mIsDirty = true; +} + +void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) +{ +	slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); +	if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached + +	LLLandmark* lm = gLandmarkList.getAsset(asset_id, +		boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); +	if (lm) +	{ +		onLandmarkLoaded(asset_id, lm); +	} +} + +// static +void LLFavoritesOrderStorage::destroyClass() +{ +	LLFavoritesOrderStorage::instance().cleanup(); +	if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) +	{ +		LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); +	} +	else +	{ +		LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); +	} +} + +void LLFavoritesOrderStorage::load() +{ +	// load per-resident sorting information +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); + +	LLSD settings_llsd; +	llifstream file; +	file.open(filename); +	if (file.is_open()) +	{ +		LLSDSerialize::fromXML(settings_llsd, file); +	} + +	for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); +		iter != settings_llsd.endMap(); ++iter) +	{ +		mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); +	} +} + +void LLFavoritesOrderStorage::saveFavoritesSLURLs() +{ +	// Do not change the file if we are not logged in yet. +	if (!LLLoginInstance::getInstance()->authSuccess()) +	{ +		llwarns << "Cannot save favorites: not logged in" << llendl; +		return; +	} + +	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); +	if (user_dir.empty()) +	{ +		llwarns << "Cannot save favorites: empty user dir name" << llendl; +		return; +	} + +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	llifstream in_file; +	in_file.open(filename); +	LLSD fav_llsd; +	if (in_file.is_open()) +	{ +		LLSDSerialize::fromXML(fav_llsd, in_file); +	} + +	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + +	LLSD user_llsd; +	for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) +	{ +		LLSD value; +		value["name"] = (*it)->getName(); +		value["asset_id"] = (*it)->getAssetUUID(); + +		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); +		if (slurl_iter != mSLURLs.end()) +		{ +			lldebugs << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" <<  slurl_iter->second << ", value=" << value << llendl; +			value["slurl"] = slurl_iter->second; +			user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value; +		} +		else +		{ +			llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; +		} +	} + +	LLAvatarName av_name; +	LLAvatarNameCache::get( gAgentID, &av_name ); +	lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; +	fav_llsd[av_name.getLegacyName()] = user_llsd; + +	llofstream file; +	file.open(filename); +	LLSDSerialize::toPrettyXML(fav_llsd, file); +} + +void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() +{ +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	LLSD fav_llsd; +	llifstream file; +	file.open(filename); +	if (!file.is_open()) return; +	LLSDSerialize::fromXML(fav_llsd, file); + +	LLAvatarName av_name; +	LLAvatarNameCache::get( gAgentID, &av_name ); +	lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; +	if (fav_llsd.has(av_name.getLegacyName())) +	{ +		fav_llsd.erase(av_name.getLegacyName()); +	} + +	llofstream out_file; +	out_file.open(filename); +	LLSDSerialize::toPrettyXML(fav_llsd, out_file); + +} + +void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) +{ +	if (!landmark) return; + +	LLVector3d pos_global; +	if (!landmark->getGlobalPos(pos_global)) +	{ +		// If global position was unknown on first getGlobalPos() call +		// it should be set for the subsequent calls. +		landmark->getGlobalPos(pos_global); +	} + +	if (!pos_global.isExactlyZero()) +	{ +		LLLandmarkActions::getSLURLfromPosGlobal(pos_global, +			boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); +	} +} + +void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) +{ +	lldebugs << "Saving landmark SLURL: " << slurl << llendl; +	mSLURLs[asset_id] = slurl; +} + +void LLFavoritesOrderStorage::save() +{ +	// nothing to save if clean +	if (!mIsDirty) return; + +	// If we quit from the login screen we will not have an SL account +	// name.  Don't try to save, otherwise we'll dump a file in +	// C:\Program Files\SecondLife\ or similar. JC +	std::string user_dir = gDirUtilp->getLindenUserDir(); +	if (!user_dir.empty()) +	{ +		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); +		LLSD settings_llsd; + +		for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) +		{ +			settings_llsd[iter->first.asString()] = iter->second; +		} + +		llofstream file; +		file.open(filename); +		LLSDSerialize::toPrettyXML(settings_llsd, file); +	} +} + +void LLFavoritesOrderStorage::cleanup() +{ +	// nothing to clean +	if (!mIsDirty) return; + +	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + +	IsNotInFavorites is_not_in_fav(items); + +	sort_index_map_t  aTempMap; +	//copy unremoved values from mSortIndexes to aTempMap +	std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),  +		inserter(aTempMap, aTempMap.begin()), +		is_not_in_fav); + +	//Swap the contents of mSortIndexes and aTempMap +	mSortIndexes.swap(aTempMap); +} + +void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array_t& items ) +{ +	int sortField = 0; + +	// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field +	for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) +	{ +		LLViewerInventoryItem* item = *i; + +		setSortIndex(item, ++sortField); + +		item->setComplete(TRUE); +		item->updateServer(FALSE); + +		gInventory.updateItem(item); + +		// Tell the parent folder to refresh its sort order. +		gInventory.addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); +	} + +	gInventory.notifyObservers(); +} + +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: +	bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) +	{ +		return LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID())  +			< LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); +	} +}; + +// * @param source_item_id - LLUUID of the source item to be moved into new position +// * @param target_item_id - LLUUID of the target item before which source item should be placed. +void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +{ +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	LLIsType is_type(LLAssetType::AT_LANDMARK); +	LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + +	// ensure items are sorted properly before changing order. EXT-3498 +	std::sort(items.begin(), items.end(), LLViewerInventoryItemSort()); + +	// update order +	gInventory.updateItemsOrder(items, source_item_id, target_item_id); + +	saveItemsOrder(items); +} + +void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) +{ +	if (mTargetLandmarkId.isNull()) return; + +	LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); +}  // EOF diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 447d30f1f4..e000adc4aa 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -33,6 +33,7 @@  #include "llinventoryobserver.h"  #include "llinventorymodel.h" +#include "llviewerinventory.h"  class LLMenuItemCallGL;  class LLToggleableMenu; @@ -161,5 +162,115 @@ private:  	boost::signals2::connection mEndDragConnection;  }; +class AddFavoriteLandmarkCallback : public LLInventoryCallback +{ +public: +	AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} +	void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } + +private: +	void fire(const LLUUID& inv_item); + +	LLUUID mTargetLandmarkId; +}; + +/** + * Class to store sorting order of favorites landmarks in a local file. EXT-3985. + * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. + * Data are stored in user home directory. + */ +class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> +	, public LLDestroyClass<LLFavoritesOrderStorage> +{ +	LOG_CLASS(LLFavoritesOrderStorage); +public: +	/** +	 * Sets sort index for specified with LLUUID favorite landmark +	 */ +	void setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index); + +	/** +	 * Gets sort index for specified with LLUUID favorite landmark +	 */ +	S32 getSortIndex(const LLUUID& inv_item_id); +	void removeSortIndex(const LLUUID& inv_item_id); + +	void getSLURL(const LLUUID& asset_id); + +	// Saves current order of the passed items using inventory item sort field. +	// Resets 'items' sort fields and saves them on server. +	// Is used to save order for Favorites folder. +	void saveItemsOrder(const LLInventoryModel::item_array_t& items); + +	void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); + +	/** +	 * Implementation of LLDestroyClass. Calls cleanup() instance method. +	 * +	 * It is important this callback is called before gInventory is cleaned. +	 * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), +	 * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. +	 * @see cleanup() +	 */ +	static void destroyClass(); + +	const static S32 NO_INDEX; +private: +	friend class LLSingleton<LLFavoritesOrderStorage>; +	LLFavoritesOrderStorage() : mIsDirty(false) { load(); } +	~LLFavoritesOrderStorage() { save(); } + +	/** +	 * Removes sort indexes for items which are not in Favorites bar for now. +	 */ +	void cleanup(); + +	const static std::string SORTING_DATA_FILE_NAME; + +	void load(); +	void save(); + +	void saveFavoritesSLURLs(); + +	// Remove record of current user's favorites from file on disk. +	void removeFavoritesRecordOfUser(); + +	void onLandmarkLoaded(const LLUUID& asset_id, class LLLandmark* landmark); +	void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); + +	typedef std::map<LLUUID, S32> sort_index_map_t; +	sort_index_map_t mSortIndexes; + +	typedef std::map<LLUUID, std::string> slurls_map_t; +	slurls_map_t mSLURLs; + +	bool mIsDirty; + +	struct IsNotInFavorites +	{ +		IsNotInFavorites(const LLInventoryModel::item_array_t& items) +			: mFavoriteItems(items) +		{ + +		} + +		/** +		 * Returns true if specified item is not found among inventory items +		 */ +		bool operator()(const sort_index_map_t::value_type& id_index_pair) const +		{ +			LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first); +			if (item.isNull()) return true; + +			LLInventoryModel::item_array_t::const_iterator found_it = +				std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); + +			return found_it == mFavoriteItems.end(); +		} +	private: +		LLInventoryModel::item_array_t mFavoriteItems; +	}; + +};  #endif // LL_LLFAVORITESBARCTRL_H diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 9745bb6d64..606d77f645 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -44,6 +44,8 @@  #include "llvoavatar.h"  /*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f; +std::vector<LLVolumeImplFlexible*> LLVolumeImplFlexible::sInstanceList; +std::vector<S32> LLVolumeImplFlexible::sUpdateDelay;  static LLFastTimer::DeclareTimer FTM_FLEXIBLE_REBUILD("Rebuild");  static LLFastTimer::DeclareTimer FTM_DO_FLEXIBLE_UPDATE("Update"); @@ -70,8 +72,45 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectD  	{  		mVO->mDrawable->makeActive() ;  	} + +	mInstanceIndex = sInstanceList.size(); +	sInstanceList.push_back(this); +	sUpdateDelay.push_back(0);  }//----------------------------------------------- +LLVolumeImplFlexible::~LLVolumeImplFlexible() +{ +	S32 end_idx = sInstanceList.size()-1; +	 +	if (end_idx != mInstanceIndex) +	{ +		sInstanceList[mInstanceIndex] = sInstanceList[end_idx]; +		sInstanceList[mInstanceIndex]->mInstanceIndex = mInstanceIndex; +		sUpdateDelay[mInstanceIndex] = sUpdateDelay[end_idx]; +	} + +	sInstanceList.pop_back(); +	sUpdateDelay.pop_back(); +} + +//static +void LLVolumeImplFlexible::updateClass() +{ +	std::vector<S32>::iterator delay_iter = sUpdateDelay.begin(); + +	for (std::vector<LLVolumeImplFlexible*>::iterator iter = sInstanceList.begin(); +			iter != sInstanceList.end(); +			++iter) +	{ +		--(*delay_iter); +		if (*delay_iter <= 0) +		{ +			(*iter)->doIdleUpdate(); +		} +		++delay_iter; +	} +} +  LLVector3 LLVolumeImplFlexible::getFramePosition() const  {  	return mVO->getRenderPosition(); @@ -296,7 +335,7 @@ void LLVolumeImplFlexible::updateRenderRes()  // optimization similar to what Havok does for objects that are stationary.   //---------------------------------------------------------------------------------  static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); -void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVolumeImplFlexible::doIdleUpdate()  {  	LLDrawable* drawablep = mVO->mDrawable; @@ -304,13 +343,8 @@ void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6  	{  		//LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); -		//flexible objects never go static -		drawablep->mQuietCount = 0; -		if (!drawablep->isRoot()) -		{ -			LLViewerObject* parent = (LLViewerObject*) mVO->getParent(); -			parent->mDrawable->mQuietCount = 0; -		} +		//ensure drawable is active +		drawablep->makeActive();  		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))  		{ @@ -321,12 +355,18 @@ void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6  				updateRenderRes();  				gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE);  			} -			else if	(visible && -				!drawablep->isState(LLDrawable::IN_REBUILD_Q1) && +			else +			{ +				F32 pixel_area = mVO->getPixelArea(); + +				U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; + +				if	(visible) +				{ +					if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1) &&  				mVO->getPixelArea() > 256.f)  			{  				U32 id; -				F32 pixel_area = mVO->getPixelArea();  				if (mVO->isRootEdit())  				{ @@ -338,15 +378,23 @@ void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6  					id = parent->getVolumeInterfaceID();  				} -				U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; -  				if ((LLDrawable::getCurrentFrame()+id)%update_period == 0)  				{ +							sUpdateDelay[mInstanceIndex] = (S32) update_period-1; +  					updateRenderRes(); +  					gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE);  				}  			}  		} +				else +				{ +					sUpdateDelay[mInstanceIndex] = (S32) update_period; +	} +} + +		}  	}  } @@ -369,8 +417,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate()  	if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible())   	{  		BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE; - -		doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0); +		doIdleUpdate();  		if (!force_update || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))  		{ diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h index 56d579d86f..beb281a906 100644 --- a/indra/newview/llflexibleobject.h +++ b/indra/newview/llflexibleobject.h @@ -70,8 +70,16 @@ struct LLFlexibleObjectSection  //---------------------------------------------------------  class LLVolumeImplFlexible : public LLVolumeInterface  { +private: +	static std::vector<LLVolumeImplFlexible*> sInstanceList; +	static std::vector<S32> sUpdateDelay; +	S32 mInstanceIndex; +  	public: +		static void updateClass(); +  		LLVolumeImplFlexible(LLViewerObject* volume, LLFlexibleObjectData* attributes); +		~LLVolumeImplFlexible();  		// Implements LLVolumeInterface  		U32 getID() const { return mID; } @@ -79,7 +87,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface  		LLQuaternion getFrameRotation() const;  		LLVolumeInterfaceType getInterfaceType() const		{ return INTERFACE_FLEXIBLE; }  		void updateRenderRes(); -		void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +		void doIdleUpdate();  		BOOL doUpdateGeometry(LLDrawable *drawable);  		LLVector3 getPivotPosition() const;  		void onSetVolume(const LLVolumeParams &volume_params, const S32 detail); diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 0290e7cdf0..47acdf7057 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -58,7 +58,8 @@ static std::map<LLUUID, LLAvatarName> sAvatarNameMap;  LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,  												   BOOL allow_multiple, -												   BOOL closeOnSelect) +												   BOOL closeOnSelect, +												   BOOL skip_agent)  {  	// *TODO: Use a key to allow this not to be an effective singleton  	LLFloaterAvatarPicker* floater =  @@ -73,6 +74,7 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,  	floater->setAllowMultiple(allow_multiple);  	floater->mNearMeListComplete = FALSE;  	floater->mCloseOnSelect = closeOnSelect; +	floater->mExcludeAgentFromSearchResults = skip_agent;  	if (!closeOnSelect)  	{ @@ -581,35 +583,38 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*  		msg->getUUIDFast(  _PREHASH_Data,_PREHASH_AvatarID,	avatar_id, i);  		msg->getStringFast(_PREHASH_Data,_PREHASH_FirstName, first_name, i);  		msg->getStringFast(_PREHASH_Data,_PREHASH_LastName,	last_name, i); -	 -		std::string avatar_name; -		if (avatar_id.isNull()) -		{ -			LLStringUtil::format_map_t map; -			map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString(); -			avatar_name = floater->getString("not_found", map); -			search_results->setEnabled(FALSE); -			floater->getChildView("ok_btn")->setEnabled(FALSE); -		} -		else + +		if (avatar_id != agent_id || !floater->isExcludeAgentFromSearchResults()) // exclude agent from search results?  		{ -			avatar_name = LLCacheName::buildFullName(first_name, last_name); -			search_results->setEnabled(TRUE); -			found_one = TRUE; +			std::string avatar_name; +			if (avatar_id.isNull()) +			{ +				LLStringUtil::format_map_t map; +				map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString(); +				avatar_name = floater->getString("not_found", map); +				search_results->setEnabled(FALSE); +				floater->getChildView("ok_btn")->setEnabled(FALSE); +			} +			else +			{ +				avatar_name = LLCacheName::buildFullName(first_name, last_name); +				search_results->setEnabled(TRUE); +				found_one = TRUE; -			LLAvatarName av_name; -			av_name.mLegacyFirstName = first_name; -			av_name.mLegacyLastName = last_name; -			av_name.mDisplayName = avatar_name; -			const LLUUID& agent_id = avatar_id; -			sAvatarNameMap[agent_id] = av_name; +				LLAvatarName av_name; +				av_name.mLegacyFirstName = first_name; +				av_name.mLegacyLastName = last_name; +				av_name.mDisplayName = avatar_name; +				const LLUUID& agent_id = avatar_id; +				sAvatarNameMap[agent_id] = av_name; +			} +			LLSD element; +			element["id"] = avatar_id; // value +			element["columns"][0]["column"] = "name"; +			element["columns"][0]["value"] = avatar_name; +			search_results->addElement(element);  		} -		LLSD element; -		element["id"] = avatar_id; // value -		element["columns"][0]["column"] = "name"; -		element["columns"][0]["value"] = avatar_name; -		search_results->addElement(element);  	}  	if (found_one) @@ -624,52 +629,58 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*  void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD& content)  {  	// Check for out-of-date query -	if (query_id != mQueryID) return; +	if (query_id == mQueryID) +	{ +		LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("SearchResults"); -	LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("SearchResults"); +		LLSD agents = content["agents"]; + +		// clear "Searching" label on first results +		search_results->deleteAllItems(); -	LLSD agents = content["agents"]; -	if (agents.size() == 0) -	{ -		LLStringUtil::format_map_t map; -		map["[TEXT]"] = childGetText("Edit");  		LLSD item; -		item["id"] = LLUUID::null; -		item["columns"][0]["column"] = "name"; -		item["columns"][0]["value"] = getString("not_found", map); -		search_results->addElement(item); -		search_results->setEnabled(false); -		getChildView("ok_btn")->setEnabled(false); -		return; -	} +		LLSD::array_const_iterator it = agents.beginArray(); +		for ( ; it != agents.endArray(); ++it) +		{ +			const LLSD& row = *it; +			if (row["id"].asUUID() != gAgent.getID() || !mExcludeAgentFromSearchResults) +			{ +				item["id"] = row["id"]; +				LLSD& columns = item["columns"]; +				columns[0]["column"] = "name"; +				columns[0]["value"] = row["display_name"]; +				columns[1]["column"] = "username"; +				columns[1]["value"] = row["username"]; +				search_results->addElement(item); + +				// add the avatar name to our list +				LLAvatarName avatar_name; +				avatar_name.fromLLSD(row); +				sAvatarNameMap[row["id"].asUUID()] = avatar_name; +			} +		} -	// clear "Searching" label on first results -	search_results->deleteAllItems(); - -	LLSD item; -	LLSD::array_const_iterator it = agents.beginArray(); -	for ( ; it != agents.endArray(); ++it) -	{ -		const LLSD& row = *it; -		item["id"] = row["id"]; -		LLSD& columns = item["columns"]; -		columns[0]["column"] = "name"; -		columns[0]["value"] = row["display_name"]; -		columns[1]["column"] = "username"; -		columns[1]["value"] = row["username"]; -		search_results->addElement(item); - -		// add the avatar name to our list -		LLAvatarName avatar_name; -		avatar_name.fromLLSD(row); -		sAvatarNameMap[row["id"].asUUID()] = avatar_name; -	} - -	getChildView("ok_btn")->setEnabled(true); -	search_results->setEnabled(true); -	search_results->selectFirstItem(); -	onList(); -	search_results->setFocus(TRUE); +		if (search_results->isEmpty()) +		{ +			LLStringUtil::format_map_t map; +			map["[TEXT]"] = childGetText("Edit"); +			LLSD item; +			item["id"] = LLUUID::null; +			item["columns"][0]["column"] = "name"; +			item["columns"][0]["value"] = getString("not_found", map); +			search_results->addElement(item); +			search_results->setEnabled(false); +			getChildView("ok_btn")->setEnabled(false); +		} +		else +		{ +			getChildView("ok_btn")->setEnabled(true); +			search_results->setEnabled(true); +			search_results->selectFirstItem(); +			onList(); +			search_results->setFocus(TRUE); +		} +	}  }  //static diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 96c039443a..7067cd7b3e 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -45,7 +45,8 @@ public:  	// Call this to select an avatar.	  	static LLFloaterAvatarPicker* show(select_callback_t callback,   									   BOOL allow_multiple = FALSE, -									   BOOL closeOnSelect = FALSE); +									   BOOL closeOnSelect = FALSE, +									   BOOL skip_agent = FALSE);  	LLFloaterAvatarPicker(const LLSD& key);  	virtual ~LLFloaterAvatarPicker(); @@ -63,6 +64,7 @@ public:  						   std::string& tooltip_msg);  	void openFriendsTab(); +	BOOL isExcludeAgentFromSearchResults() {return mExcludeAgentFromSearchResults;}  private:  	void editKeystroke(class LLLineEditor* caller, void* user_data); @@ -88,9 +90,10 @@ private:  	virtual BOOL handleKeyHere(KEY key, MASK mask);  	LLUUID				mQueryID; -	int				mNumResultsReturned; +	int				    mNumResultsReturned;  	BOOL				mNearMeListComplete;  	BOOL				mCloseOnSelect; +	BOOL                mExcludeAgentFromSearchResults;  	validate_signal_t mOkButtonValidateSignal;  	select_callback_t mSelectionCallback; diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp new file mode 100644 index 0000000000..c77a9e74bb --- /dev/null +++ b/indra/newview/llfloaterconversationlog.cpp @@ -0,0 +1,127 @@ +/** + * @file llfloaterconversationlog.cpp + * @brief Functionality of the "conversation log" floater + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llconversationloglist.h" +#include "llfiltereditor.h" +#include "llfloaterconversationlog.h" +#include "llmenubutton.h" + +LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) +:	LLFloater(key), +	mConversationLogList(NULL) +{ +	mCommitCallbackRegistrar.add("CallLog.Action",	boost::bind(&LLFloaterConversationLog::onCustomAction,  this, _2)); +	mEnableCallbackRegistrar.add("CallLog.Check",	boost::bind(&LLFloaterConversationLog::isActionChecked, this, _2)); +} + +BOOL LLFloaterConversationLog::postBuild() +{ +	mConversationLogList = getChild<LLConversationLogList>("conversation_log_list"); + +	switch (gSavedSettings.getU32("CallLogSortOrder")) +	{ +	case E_SORT_BY_NAME: +		mConversationLogList->sortByName(); +		break; + +	case E_SORT_BY_DATE: +		mConversationLogList->sortByDate(); +		break; +	} + +	// Use the context menu of the Conversation list for the Conversation tab gear menu. +	LLToggleableMenu* conversations_gear_menu = mConversationLogList->getContextMenu(); +	if (conversations_gear_menu) +	{ +		getChild<LLMenuButton>("conversations_gear_btn")->setMenu(conversations_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); +	} + +	getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); + +	return LLFloater::postBuild(); +} + +void LLFloaterConversationLog::draw() +{ +	LLFloater::draw(); +} + +void LLFloaterConversationLog::onFilterEdit(const std::string& search_string) +{ +	std::string filter = search_string; +	LLStringUtil::trimHead(filter); + +	mConversationLogList->setNameFilter(filter); +} + + +void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) +{ +	const std::string command_name = userdata.asString(); + +	if ("sort_by_name" == command_name) +	{ +		mConversationLogList->sortByName(); +		gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); +	} +	else if ("sort_by_date" == command_name) +	{ +		mConversationLogList->sortByDate(); +		gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); +	} +	else if ("sort_friends_on_top" == command_name) +	{ +		mConversationLogList->toggleSortFriendsOnTop(); +	} +} + +bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) +{ +	return true; +} + +bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) +{ +	const std::string command_name = userdata.asString(); + +	U32 sort_order = gSavedSettings.getU32("CallLogSortOrder"); + +	if ("sort_by_name" == command_name) +	{ +		return sort_order == E_SORT_BY_NAME; +	} +	else if ("sort_by_date" == command_name) +	{ +		return sort_order == E_SORT_BY_DATE; +	} +	else if ("sort_friends_on_top" == command_name) +	{ +		return gSavedSettings.getBOOL("SortFriendsFirst"); +	} + +	return false; +} diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h new file mode 100644 index 0000000000..7d788c0290 --- /dev/null +++ b/indra/newview/llfloaterconversationlog.h @@ -0,0 +1,61 @@ +/** + * @file llfloaterconversationlog.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERCONVERSATIONLOG_H_ +#define LL_LLFLOATERCONVERSATIONLOG_H_ + +#include "llfloater.h" + +class LLConversationLogList; + +class LLFloaterConversationLog : public LLFloater +{ +public: + +	typedef enum e_sort_oder{ +		E_SORT_BY_NAME = 0, +		E_SORT_BY_DATE = 1, +	} ESortOrder; + +	LLFloaterConversationLog(const LLSD& key); +	virtual ~LLFloaterConversationLog(){}; + +	virtual BOOL postBuild(); + +	virtual void draw(); + +	void onFilterEdit(const std::string& search_string); + +private: + +	void onCustomAction (const LLSD& userdata); +	bool isActionEnabled(const LLSD& userdata); +	bool isActionChecked(const LLSD& userdata); + +	LLConversationLogList* mConversationLogList; +}; + + +#endif /* LLFLOATERCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp new file mode 100644 index 0000000000..e8554bb066 --- /dev/null +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -0,0 +1,112 @@ +/** + * @file llfloaterconversationpreview.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llconversationlog.h" +#include "llfloaterconversationpreview.h" +#include "llimview.h" +#include "lllineeditor.h" + +LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) +:	LLFloater(session_id), +	mChatHistory(NULL), +	mSessionID(session_id.asUUID()) +{} + +BOOL LLFloaterConversationPreview::postBuild() +{ +	mChatHistory = getChild<LLChatHistory>("chat_history"); + +	const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); +	if (conv) +	{ +		std::string name = conv->getConversationName(); +		LLStringUtil::format_map_t args; +		args["[NAME]"] = name; +		std::string title = getString("Title", args); +		setTitle(title); + +		getChild<LLLineEditor>("description")->setValue(name); +	} + +	return LLFloater::postBuild(); +} + +void LLFloaterConversationPreview::draw() +{ +	LLFloater::draw(); +} + +void LLFloaterConversationPreview::onOpen(const LLSD& session_id) +{ +	const LLConversation* conv = LLConversationLog::instance().getConversation(session_id); +	if (!conv) +	{ +		return; +	} +	std::list<LLSD> messages; +	std::string file = conv->getHistoryFileName(); +	LLLogChat::loadAllHistory(file, messages); + +	if (messages.size()) +	{ +		std::ostringstream message; +		std::list<LLSD>::const_iterator iter = messages.begin(); +		for (; iter != messages.end(); ++iter) +		{ +			LLSD msg = *iter; + +			std::string time	= msg["time"].asString(); +			LLUUID from_id		= msg["from_id"].asUUID(); +			std::string from	= msg["from"].asString(); +			std::string message	= msg["message"].asString(); +			bool is_history	= msg["is_history"].asBoolean(); + +			LLChat chat; +			chat.mFromID = from_id; +			chat.mSessionID = session_id; +			chat.mFromName = from; +			chat.mTimeStr = time; +			chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; +			chat.mText = message; + +			appendMessage(chat); +		} +	} +} + +void LLFloaterConversationPreview::appendMessage(const LLChat& chat) +{ +	if (!chat.mMuted) +	{ +		LLSD args; +		args["use_plain_text_chat_history"] = true; +		args["show_time"] = true; +		args["show_names_for_p2p_conv"] = true; + +		mChatHistory->appendMessage(chat); +	} +} diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h new file mode 100644 index 0000000000..cfc7c34485 --- /dev/null +++ b/indra/newview/llfloaterconversationpreview.h @@ -0,0 +1,51 @@ +/** + * @file llfloaterconversationpreview.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERCONVERSATIONPREVIEW_H_ +#define LLFLOATERCONVERSATIONPREVIEW_H_ + +#include "llchathistory.h" +#include "llfloater.h" + +class LLFloaterConversationPreview : public LLFloater +{ +public: + +	LLFloaterConversationPreview(const LLSD& session_id); +	virtual ~LLFloaterConversationPreview(){}; + +	virtual BOOL postBuild(); + +	virtual void draw(); +	virtual void onOpen(const LLSD& session_id); + +private: +	void appendMessage(const LLChat& chat); + +	LLChatHistory*	mChatHistory; +	LLUUID			mSessionID; +}; + +#endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index df8ecb6fd9..55f3d548ec 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2362,12 +2362,6 @@ LLPanelLandAccess::~LLPanelLandAccess()  void LLPanelLandAccess::refresh()  {  	LLFloater* parent_floater = gFloaterView->getParentFloater(this); -	 -	if (mListAccess) -		mListAccess->deleteAllItems(); -	if (mListBanned) -		mListBanned->deleteAllItems(); -	  	LLParcel *parcel = mParcel->getParcel();  	// Display options @@ -2385,7 +2379,11 @@ void LLPanelLandAccess::refresh()  		getChild<LLUICtrl>("GroupCheck")->setLabelArg("[GROUP]", group_name );  		// Allow list +		if (mListAccess)  		{ +			// Clear the sort order so we don't re-sort on every add. +			mListAccess->clearSortOrder(); +			mListAccess->deleteAllItems();  			S32 count = parcel->mAccessList.size();  			getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));  			getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST)); @@ -2420,13 +2418,17 @@ void LLPanelLandAccess::refresh()  					}  					suffix.append(" " + parent_floater->getString("Remaining") + ")");  				} -				if (mListAccess) -					mListAccess->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix); +				mListAccess->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix);  			} +			mListAccess->sortByName(TRUE);  		}  		// Ban List +		if(mListBanned)  		{ +			// Clear the sort order so we don't re-sort on every add. +			mListBanned->clearSortOrder(); +			mListBanned->deleteAllItems();  			S32 count = parcel->mBanList.size();  			getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count)); @@ -2464,6 +2466,7 @@ void LLPanelLandAccess::refresh()  				}  				mListBanned->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix);  			} +			mListBanned->sortByName(TRUE);  		}  		if(parcel->getRegionDenyAnonymousOverride()) @@ -2599,13 +2602,13 @@ void LLPanelLandAccess::refresh_ui()  		getChildView("AccessList")->setEnabled(can_manage_allowed);  		S32 allowed_list_count = parcel->mAccessList.size();  		getChildView("add_allowed")->setEnabled(can_manage_allowed && allowed_list_count < PARCEL_MAX_ACCESS_LIST); -		BOOL has_selected = mListAccess->getSelectionInterface()->getFirstSelectedIndex() >= 0; +		BOOL has_selected = (mListAccess && mListAccess->getSelectionInterface()->getFirstSelectedIndex() >= 0);  		getChildView("remove_allowed")->setEnabled(can_manage_allowed && has_selected);  		getChildView("BannedList")->setEnabled(can_manage_banned);  		S32 banned_list_count = parcel->mBanList.size();  		getChildView("add_banned")->setEnabled(can_manage_banned && banned_list_count < PARCEL_MAX_ACCESS_LIST); -		has_selected = mListBanned->getSelectionInterface()->getFirstSelectedIndex() >= 0; +		has_selected = (mListBanned && mListBanned->getSelectionInterface()->getFirstSelectedIndex() >= 0);  		getChildView("remove_banned")->setEnabled(can_manage_banned && has_selected);  	}  } diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 2681d4b34d..4f35c325a8 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -44,21 +44,16 @@ public:  	BOOL postBuild();  private: -	bool update(const LLSD& payload, bool passed_filter); +	bool update(const LLSD& payload);  	static void toggleClick(void* user_data);  	static void onClickNotification(void* user_data); -	static void onClickNotificationReject(void* user_data);  	LLNotificationChannelPtr mChannelPtr; -	LLNotificationChannelPtr mChannelRejectsPtr;  };  LLNotificationChannelPanel::LLNotificationChannelPanel(const LLNotificationChannelPanel::Params& p)   :	LLLayoutPanel(p)  {  	mChannelPtr = LLNotifications::instance().getChannel(p.name); -	mChannelRejectsPtr = LLNotificationChannelPtr( -		LLNotificationChannel::buildChannel(p.name() + "rejects", mChannelPtr->getParentChannelName(), -											!boost::bind(mChannelPtr->getFilter(), _1)));  	buildFromFile( "panel_notifications_channel.xml");  } @@ -68,15 +63,11 @@ BOOL LLNotificationChannelPanel::postBuild()  	header_button->setLabel(mChannelPtr->getName());  	header_button->setClickedCallback(toggleClick, this); -	mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, true)); -	mChannelRejectsPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, false)); +	mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1));  	LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("notifications_list");  	scroll->setDoubleClickCallback(onClickNotification, this);  	scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0)); -	scroll = getChild<LLScrollListCtrl>("notification_rejects_list"); -	scroll->setDoubleClickCallback(onClickNotificationReject, this); -	scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0));  	return TRUE;  } @@ -97,8 +88,6 @@ void LLNotificationChannelPanel::toggleClick(void *user_data)  	// turn off tab stop for collapsed panel  	self->getChild<LLScrollListCtrl>("notifications_list")->setTabStop(!header_button->getToggleState());  	self->getChild<LLScrollListCtrl>("notifications_list")->setVisible(!header_button->getToggleState()); -	self->getChild<LLScrollListCtrl>("notification_rejects_list")->setTabStop(!header_button->getToggleState()); -	self->getChild<LLScrollListCtrl>("notification_rejects_list")->setVisible(!header_button->getToggleState());  }  /*static*/ @@ -118,24 +107,7 @@ void LLNotificationChannelPanel::onClickNotification(void* user_data)  	}  } -/*static*/ -void LLNotificationChannelPanel::onClickNotificationReject(void* user_data) -{ -	LLNotificationChannelPanel* self = (LLNotificationChannelPanel*)user_data; -	if (!self) return; -	LLScrollListItem* firstselected = self->getChild<LLScrollListCtrl>("notification_rejects_list")->getFirstSelected(); -	llassert(firstselected); -	if (firstselected) -	{ -		void* data = firstselected->getUserdata(); -		if (data) -		{ -			gFloaterView->getParentFloater(self)->addDependentFloater(new LLFloaterNotification((LLNotification*)data), TRUE); -		} -	} -} - -bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter) +bool LLNotificationChannelPanel::update(const LLSD& payload)  {  	LLNotificationPtr notification = LLNotifications::instance().find(payload["id"].asUUID());  	if (notification) @@ -151,9 +123,7 @@ bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter)  		row["columns"][2]["column"] = "date";  		row["columns"][2]["type"] = "date"; -		LLScrollListItem* sli = passed_filter ?  -			getChild<LLScrollListCtrl>("notifications_list")->addElement(row) : -			getChild<LLScrollListCtrl>("notification_rejects_list")->addElement(row); +		LLScrollListItem* sli = getChild<LLScrollListCtrl>("notifications_list")->addElement(row);  		sli->setUserdata(&(*notification));  	} diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 540f977305..18ed36d0f3 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -44,14 +44,12 @@  #include "llviewernetwork.h"  #include "llwindowshade.h" -#define USE_WINDOWSHADE_DIALOGS	0 -  ///----------------------------------------------------------------------------  /// LLOutboxNotification class  ///---------------------------------------------------------------------------- -bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify) +bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify)  {  	LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox"); @@ -60,6 +58,14 @@ bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& no  	return false;  } +void LLNotificationsUI::LLOutboxNotification::onDelete(LLNotificationPtr p) +{ +	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get()); +	if (sys_handler) +	{ +		sys_handler->onDelete(p); +	} +}  ///----------------------------------------------------------------------------  /// LLOutboxAddedObserver helper class @@ -168,9 +174,8 @@ void LLFloaterOutbox::onOpen(const LLSD& key)  	if (mOutboxId.isNull())  	{  		const bool do_not_create_folder = false; -		const bool do_not_find_in_library = false; -		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library); +		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder);  		if (outbox_id.isNull())  		{ @@ -244,8 +249,9 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)  	mOutboxInventoryPanel->setShape(inventory_placeholder_rect);  	// Set the sort order newest to oldest -	mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME);	 -	mOutboxInventoryPanel->getFilter()->markDefault(); + +	mOutboxInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME);	 +	mOutboxInventoryPanel->getFilter().markDefault();  	fetchOutboxContents(); @@ -380,7 +386,7 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	// Determine if the mouse is inside the inventory panel itself or just within the floater  	bool pointInInventoryPanel = false;  	bool pointInInventoryPanelChild = false; -	LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder(); +	LLFolderView* root_folder = mOutboxInventoryPanel->getRootFolder();  	if (mOutboxInventoryPanel->getVisible())  	{  		S32 inv_x, inv_y; @@ -437,10 +443,10 @@ void LLFloaterOutbox::onOutboxChanged()  {  	llassert(!mOutboxId.isNull()); -	if (mOutboxInventoryPanel) -	{ -		mOutboxInventoryPanel->requestSort(); -	} +	//if (mOutboxInventoryPanel) +	//{ +	//	mOutboxInventoryPanel->requestSort(); +	//}  	fetchOutboxContents(); @@ -516,52 +522,11 @@ void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content)  	updateView();  } -void LLFloaterOutbox::showNotification(const LLSD& notify) +void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification)  { -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); -	 -	if (!notification) -	{ -		llerrs << "Unable to find outbox notification!" << notify.asString() << llendl; -		 -		return; -	} - -#if USE_WINDOWSHADE_DIALOGS - -	if (mWindowShade) -	{ -		delete mWindowShade; -	} -	 -	LLRect floater_rect = getLocalRect(); -	floater_rect.mTop -= getHeaderHeight(); -	floater_rect.stretch(-5, 0); -	 -	LLWindowShade::Params params; -	params.name = "notification_shade"; -	params.rect = floater_rect; -	params.follows.flags = FOLLOWS_ALL; -	params.modal = true; -	params.can_close = false; -	params.shade_color = LLColor4::white % 0.25f; -	params.text_color = LLColor4::white; -	 -	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params); -	 -	addChild(mWindowShade); -	mWindowShade->show(notification); -	 -#else -	 -	LLNotificationsUI::LLEventHandler * handler = -		LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal"); -	 -	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler *>(handler); +	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get());  	llassert(sys_handler); -	sys_handler->processNotification(notify); -	 -#endif +	sys_handler->processNotification(notification);  } diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index 18baccf1c9..a91d8c1139 100644 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -64,7 +64,7 @@ public:  						   EAcceptance* accept,  						   std::string& tooltip_msg); -	void showNotification(const LLSD& notify); +	void showNotification(const LLNotificationPtr& notification);  	BOOL handleHover(S32 x, S32 y, MASK mask);  	void onMouseLeave(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 5752f839ce..c78a803bf3 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -425,13 +425,7 @@ void LLFloaterPreference::saveAvatarProperties( void )  BOOL LLFloaterPreference::postBuild()  { -	gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); - -	gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); - -	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); - -	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); +	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate));  	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); @@ -461,14 +455,11 @@ BOOL LLFloaterPreference::postBuild()  void LLFloaterPreference::onBusyResponseChanged()  {  	// set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise -	if (LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) -	{ -		gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE ); -	} -	else -	{ -		gSavedPerAccountSettings.setBOOL("BusyResponseChanged", FALSE ); -	} +	bool busy_flag = +			LLTrans::getString("BusyModeResponseDefault") +					!= getChild<LLUICtrl>("busy_response")->getValue().asString(); + +	gSavedPerAccountSettings.setBOOL("BusyResponseChanged", busy_flag );  }  LLFloaterPreference::~LLFloaterPreference() @@ -553,8 +544,6 @@ void LLFloaterPreference::apply()  //	LLWString busy_response = utf8str_to_wstring(getChild<LLUICtrl>("busy_response")->getValue().asString());  //	LLWStringUtil::replaceTabsWithSpaces(busy_response, 4); - -	gSavedSettings.setBOOL("PlainTextChatHistory", getChild<LLUICtrl>("plain_text_chat_history")->getValue().asBoolean());  	if (mGotPersonalInfo)  	{  @@ -1440,8 +1429,6 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im  	getChild<LLUICtrl>("online_visibility")->setLabelArg("[DIR_VIS]", mDirectoryVisibility);  	getChildView("send_im_to_email")->setEnabled(TRUE);  	getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email); -	getChildView("plain_text_chat_history")->setEnabled(TRUE); -	getChild<LLUICtrl>("plain_text_chat_history")->setValue(gSavedSettings.getBOOL("PlainTextChatHistory"));  	getChildView("log_instant_messages")->setEnabled(TRUE);  //	getChildView("log_chat")->setEnabled(TRUE);  //	getChildView("busy_response")->setEnabled(TRUE); @@ -1523,7 +1510,8 @@ void LLFloaterPreference::onChangeMaturity()  // but the UI for this will still be enabled  void LLFloaterPreference::onClickBlockList()  { -	LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); +	LLFloaterSidePanelContainer::showPanel("people", "panel_people", +		LLSD().with("people_panel_tab_name", "blocked_panel"));  }  void LLFloaterPreference::onClickProxySettings() diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 17850ff35d..fe29bb38c7 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -287,8 +287,7 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**)  	//dispatch the message  	dispatch.dispatch(request, invoice, strings); -	LLViewerRegion* region = gAgent.getRegion(); -	panel->updateControls(region); +	panel->updateControls(gAgent.getRegion());  } @@ -1924,10 +1923,18 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region)  	BOOL manager = (region && region->isEstateManager());  	setCtrlsEnabled(god || owner || manager); +	BOOL has_allowed_avatar = getChild<LLNameListCtrl>("allowed_avatar_name_list")->getFirstSelected() ?  TRUE : FALSE; +	BOOL has_allowed_group = getChild<LLNameListCtrl>("allowed_group_name_list")->getFirstSelected() ?  TRUE : FALSE; +	BOOL has_banned_agent = getChild<LLNameListCtrl>("banned_avatar_name_list")->getFirstSelected() ?  TRUE : FALSE; +	BOOL has_estate_manager = getChild<LLNameListCtrl>("estate_manager_name_list")->getFirstSelected() ?  TRUE : FALSE; +  	getChildView("add_allowed_avatar_btn")->setEnabled(god || owner || manager); -	getChildView("remove_allowed_avatar_btn")->setEnabled(god || owner || manager); +	getChildView("remove_allowed_avatar_btn")->setEnabled(has_allowed_avatar && (god || owner || manager)); +	getChildView("allowed_avatar_name_list")->setEnabled(god || owner || manager); +	  	getChildView("add_allowed_group_btn")->setEnabled(god || owner || manager); -	getChildView("remove_allowed_group_btn")->setEnabled(god || owner || manager); +	getChildView("remove_allowed_group_btn")->setEnabled(has_allowed_group && (god || owner || manager) ); +	getChildView("allowed_group_name_list")->setEnabled(god || owner || manager);  	// Can't ban people from mainland, orientation islands, etc. because this  	// creates much network traffic and server load. @@ -1935,14 +1942,15 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region)  	bool linden_estate = isLindenEstate();  	bool enable_ban = (god || owner || manager) && !linden_estate;  	getChildView("add_banned_avatar_btn")->setEnabled(enable_ban); -	getChildView("remove_banned_avatar_btn")->setEnabled(enable_ban); +	getChildView("remove_banned_avatar_btn")->setEnabled(has_banned_agent && enable_ban); +	getChildView("banned_avatar_name_list")->setEnabled(god || owner || manager);  	getChildView("message_estate_btn")->setEnabled(god || owner || manager);  	getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager);  	// estate managers can't add estate managers  	getChildView("add_estate_manager_btn")->setEnabled(god || owner); -	getChildView("remove_estate_manager_btn")->setEnabled(god || owner); +	getChildView("remove_estate_manager_btn")->setEnabled(has_estate_manager && (god || owner));  	getChildView("estate_manager_name_list")->setEnabled(god || owner);  	refresh(); @@ -1979,10 +1987,8 @@ bool LLPanelEstateInfo::refreshFromRegion(LLViewerRegion* region)  void LLPanelEstateInfo::updateChild(LLUICtrl* child_ctrl)  { -	if (checkRemovalButton(child_ctrl->getName())) -	{ -		// do nothing -	} +	// Ensure appropriate state of the management ui. +	updateControls(gAgent.getRegion());  }  bool LLPanelEstateInfo::estateUpdate(LLMessageSystem* msg) @@ -2080,23 +2086,8 @@ void LLPanelEstateInfo::refreshFromEstate()  	getChild<LLUICtrl>("limit_payment")->setValue(estate_info.getDenyAnonymous());  	getChild<LLUICtrl>("limit_age_verified")->setValue(estate_info.getDenyAgeUnverified()); -	// If visible from mainland, disable the access allowed -	// UI, as anyone can teleport there. -	// However, gods need to be able to edit the access list for -	// linden estates, regardless of visibility, to allow object -	// and L$ transfers. -	{ -		bool visible_from_mainland = estate_info.getIsExternallyVisible(); -		bool god = gAgent.isGodlike(); -		bool linden_estate = isLindenEstate(); - -		bool enable_agent = (!visible_from_mainland || (god && linden_estate)); -		bool enable_group = enable_agent; -		bool enable_ban = !linden_estate; - -		setAccessAllowedEnabled(enable_agent, enable_group, enable_ban); -	} - +	// Ensure appriopriate state of the management UI +	updateControls(gAgent.getRegion());  	refresh();  } @@ -2225,47 +2216,6 @@ void LLPanelEstateInfo::setOwnerName(const std::string& name)  	getChild<LLUICtrl>("estate_owner")->setValue(LLSD(name));  } -void LLPanelEstateInfo::setAccessAllowedEnabled(bool enable_agent, -												bool enable_group, -												bool enable_ban) -{ -	getChildView("allow_resident_label")->setEnabled(enable_agent); -	getChildView("allowed_avatar_name_list")->setEnabled(enable_agent); -	getChildView("allowed_avatar_name_list")->setVisible( enable_agent); -	getChildView("add_allowed_avatar_btn")->setEnabled(enable_agent); -	getChildView("remove_allowed_avatar_btn")->setEnabled(enable_agent); - -	// Groups -	getChildView("allow_group_label")->setEnabled(enable_group); -	getChildView("allowed_group_name_list")->setEnabled(enable_group); -	getChildView("allowed_group_name_list")->setVisible( enable_group); -	getChildView("add_allowed_group_btn")->setEnabled(enable_group); -	getChildView("remove_allowed_group_btn")->setEnabled(enable_group); - -	// Ban -	getChildView("ban_resident_label")->setEnabled(enable_ban); -	getChildView("banned_avatar_name_list")->setEnabled(enable_ban); -	getChildView("banned_avatar_name_list")->setVisible( enable_ban); -	getChildView("add_banned_avatar_btn")->setEnabled(enable_ban); -	getChildView("remove_banned_avatar_btn")->setEnabled(enable_ban); - -	// Update removal buttons if needed -	if (enable_agent) -	{ -		checkRemovalButton("allowed_avatar_name_list"); -	} - -	if (enable_group) -	{ -		checkRemovalButton("allowed_group_name_list"); -	} - -	if (enable_ban) -	{ -		checkRemovalButton("banned_avatar_name_list"); -	} -} -  void LLPanelEstateInfo::clearAccessLists()   {  	LLNameListCtrl* name_list = getChild<LLNameListCtrl>("allowed_avatar_name_list"); @@ -2279,39 +2229,7 @@ void LLPanelEstateInfo::clearAccessLists()  	{  		name_list->deleteAllItems();  	} -} - -// enables/disables the "remove" button for the various allow/ban lists -BOOL LLPanelEstateInfo::checkRemovalButton(std::string name) -{ -	std::string btn_name = ""; -	if (name == "allowed_avatar_name_list") -	{ -		btn_name = "remove_allowed_avatar_btn"; -	} -	else if (name == "allowed_group_name_list") -	{ -		btn_name = "remove_allowed_group_btn"; -	} -	else if (name == "banned_avatar_name_list") -	{ -		btn_name = "remove_banned_avatar_btn"; -	} -	else if (name == "estate_manager_name_list") -	{ -		//ONLY OWNER CAN ADD /DELET ESTATE MANAGER -		LLViewerRegion* region = gAgent.getRegion(); -		if (region && (region->getOwner() == gAgent.getID())) -		{ -			btn_name = "remove_estate_manager_btn"; -		} -	} - -	// enable the remove button if something is selected -	LLNameListCtrl* name_list = getChild<LLNameListCtrl>(name); -	getChildView(btn_name)->setEnabled(name_list && name_list->getFirstSelected() ? TRUE : FALSE); - -	return (btn_name != ""); +	updateControls(gAgent.getRegion());  }  // static @@ -2792,15 +2710,15 @@ bool LLDispatchSetEstateAccess::operator()(  		if (allowed_agent_name_list)  		{ -			//allowed_agent_name_list->deleteAllItems(); +			// Don't sort these as we add them, sort them when we are done. +			allowed_agent_name_list->clearSortOrder();  			for (S32 i = 0; i < num_allowed_agents && i < ESTATE_MAX_ACCESS_IDS; i++)  			{  				LLUUID id;  				memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */  				allowed_agent_name_list->addNameItem(id);  			} -			panel->getChildView("remove_allowed_avatar_btn")->setEnabled(allowed_agent_name_list->getFirstSelected() ? TRUE : FALSE); -			allowed_agent_name_list->sortByColumnIndex(0, TRUE); +			allowed_agent_name_list->sortByName(TRUE);  		}  	} @@ -2817,6 +2735,8 @@ bool LLDispatchSetEstateAccess::operator()(  		if (allowed_group_name_list)  		{ +			// Don't sort these as we add them, sort them when we are done. +			allowed_group_name_list->clearSortOrder();  			allowed_group_name_list->deleteAllItems();  			for (S32 i = 0; i < num_allowed_groups && i < ESTATE_MAX_GROUP_IDS; i++)  			{ @@ -2824,8 +2744,7 @@ bool LLDispatchSetEstateAccess::operator()(  				memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */  				allowed_group_name_list->addGroupNameItem(id);  			} -			panel->getChildView("remove_allowed_group_btn")->setEnabled(allowed_group_name_list->getFirstSelected() ? TRUE : FALSE); -			allowed_group_name_list->sortByColumnIndex(0, TRUE); +			allowed_group_name_list->sortByName(TRUE);  		}  	} @@ -2849,15 +2768,16 @@ bool LLDispatchSetEstateAccess::operator()(  		if (banned_agent_name_list)  		{ -			//banned_agent_name_list->deleteAllItems(); +			// Don't sort these as we add them, sort them when we are done. +			banned_agent_name_list->clearSortOrder(); +  			for (S32 i = 0; i < num_banned_agents && i < ESTATE_MAX_ACCESS_IDS; i++)  			{  				LLUUID id;  				memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */  				banned_agent_name_list->addNameItem(id);  			} -			panel->getChildView("remove_banned_avatar_btn")->setEnabled(banned_agent_name_list->getFirstSelected() ? TRUE : FALSE); -			banned_agent_name_list->sortByColumnIndex(0, TRUE); +			banned_agent_name_list->sortByName(TRUE);  		}  	} @@ -2872,6 +2792,9 @@ bool LLDispatchSetEstateAccess::operator()(  			panel->getChild<LLNameListCtrl>("estate_manager_name_list");  		if (estate_manager_name_list)  		{	 +			// Don't sort these as we add them, sort them when we are done. +			estate_manager_name_list->clearSortOrder(); +  			estate_manager_name_list->deleteAllItems();		// Clear existing entries  			// There should be only ESTATE_MAX_MANAGERS people in the list, but if the database gets more (SL-46107) don't  @@ -2883,11 +2806,13 @@ bool LLDispatchSetEstateAccess::operator()(  				memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */  				estate_manager_name_list->addNameItem(id);  			} -			panel->getChildView("remove_estate_manager_btn")->setEnabled(estate_manager_name_list->getFirstSelected() ? TRUE : FALSE); -			estate_manager_name_list->sortByColumnIndex(0, TRUE); +			estate_manager_name_list->sortByName(TRUE);  		}  	} +	// Update the buttons which may change based on the list contents but also needs to account for general access features. +	panel->updateControls(gAgent.getRegion()); +  	return true;  } diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index e36ef4604b..f0499f1903 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -312,9 +312,6 @@ public:  	const std::string getOwnerName() const;  	void setOwnerName(const std::string& name); -	// If visible from mainland, allowed agent and allowed groups -	// are ignored, so must disable UI. -	void setAccessAllowedEnabled(bool enable_agent, bool enable_group, bool enable_ban);  protected:  	virtual BOOL sendUpdate();  	// confirmation dialog callback @@ -324,7 +321,6 @@ protected:  	void commitEstateManagers();  	void clearAccessLists(); -	BOOL checkRemovalButton(std::string name);  	BOOL checkSunHourSlider(LLUICtrl* child_ctrl);  	U32 mEstateID; diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 5385977d95..96b5c6b09b 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -61,7 +61,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na  	if (!getVisible())  	{ -		openFloater(); +	openFloater();  	}  	LLPanel* panel = NULL; @@ -69,10 +69,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na  	LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent());  	if (container)  	{ -		LLSD new_params = params; -		new_params[LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME] = panel_name; -		container->onOpen(new_params); - +		container->openPanel(panel_name, params);  		panel = container->getCurrentPanel();  	}  	else if ((panel = dynamic_cast<LLPanel*>(view)) != NULL) diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 48484786f6..7cf358c8e5 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -657,8 +657,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)  	mBtnEdit	->setToggleState( edit_visible );  	mRadioGroupEdit->setVisible( edit_visible ); -	bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts"); -	getChildView("RenderingCost")->setVisible( !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost); +	//bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts"); +	//getChildView("RenderingCost")->setVisible( !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost);  	mBtnLink->setVisible(edit_visible);  	mBtnUnlink->setVisible(edit_visible); diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 87d048c15b..2d91a61b54 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -82,6 +82,7 @@ LLFloaterTopObjects::LLFloaterTopObjects(const LLSD& key)  	mCommitCallbackRegistrar.add("TopObjects.Refresh",			boost::bind(&LLFloaterTopObjects::onRefresh, this));  	mCommitCallbackRegistrar.add("TopObjects.GetByObjectName",	boost::bind(&LLFloaterTopObjects::onGetByObjectName, this));  	mCommitCallbackRegistrar.add("TopObjects.GetByOwnerName",	boost::bind(&LLFloaterTopObjects::onGetByOwnerName, this)); +	mCommitCallbackRegistrar.add("TopObjects.GetByParcelName",	boost::bind(&LLFloaterTopObjects::onGetByParcelName, this));  	mCommitCallbackRegistrar.add("TopObjects.CommitObjectsList",boost::bind(&LLFloaterTopObjects::onCommitObjectsList, this));  } @@ -99,21 +100,6 @@ BOOL LLFloaterTopObjects::postBuild()  	setDefaultBtn("show_beacon_btn"); -	/* -	LLLineEditor* line_editor = getChild<LLLineEditor>("owner_name_editor"); -	if (line_editor) -	{ -		line_editor->setCommitOnFocusLost(FALSE); -		line_editor->setCommitCallback(onGetByOwnerName, this); -	} - -	line_editor = getChild<LLLineEditor>("object_name_editor"); -	if (line_editor) -	{ -		line_editor->setCommitOnFocusLost(FALSE); -		line_editor->setCommitCallback(onGetByObjectName, this); -	}*/ -  	mCurrentMode = STAT_REPORT_TOP_SCRIPTS;  	mFlags = 0;  	mFilter.clear(); @@ -168,9 +154,11 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)  		F32 score;  		std::string name_buf;  		std::string owner_buf; +		std::string parcel_buf("unknown");  		F32 mono_score = 0.f;  		bool have_extended_data = false;  		S32 public_urls = 0; +		F32 script_memory = 0.f;  		msg->getU32Fast(_PREHASH_ReportData, _PREHASH_TaskLocalID, task_local_id, block);  		msg->getUUIDFast(_PREHASH_ReportData, _PREHASH_TaskID, task_id, block); @@ -180,12 +168,18 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)  		msg->getF32Fast(_PREHASH_ReportData, _PREHASH_Score, score, block);  		msg->getStringFast(_PREHASH_ReportData, _PREHASH_TaskName, name_buf, block);  		msg->getStringFast(_PREHASH_ReportData, _PREHASH_OwnerName, owner_buf, block); +  		if(msg->has("DataExtended"))  		{  			have_extended_data = true;  			msg->getU32("DataExtended", "TimeStamp", time_stamp, block);  			msg->getF32("DataExtended", "MonoScore", mono_score, block);  			msg->getS32("DataExtended", "PublicURLs", public_urls, block); +			if (msg->getSize("DataExtended", "ParcelName") > 0) +			{ +				msg->getString("DataExtended", "ParcelName", parcel_buf, block); +				msg->getF32("DataExtended", "Size", script_memory, block); +			}  		}  		LLSD element; @@ -193,13 +187,14 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)  		element["id"] = task_id;  		LLSD columns; -		columns[0]["column"] = "score"; -		columns[0]["value"] = llformat("%0.3f", score); -		columns[0]["font"] = "SANSSERIF"; +		S32 column_num = 0; +		columns[column_num]["column"] = "score"; +		columns[column_num]["value"] = llformat("%0.3f", score); +		columns[column_num++]["font"] = "SANSSERIF"; -		columns[1]["column"] = "name"; -		columns[1]["value"] = name_buf; -		columns[1]["font"] = "SANSSERIF"; +		columns[column_num]["column"] = "name"; +		columns[column_num]["value"] = name_buf; +		columns[column_num++]["font"] = "SANSSERIF";  		// Owner names can have trailing spaces sent from server  		LLStringUtil::trim(owner_buf); @@ -215,28 +210,33 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)  			// ...just strip out legacy "Resident" name  			owner_buf = LLCacheName::cleanFullName(owner_buf);  		} -		columns[2]["column"] = "owner"; -		columns[2]["value"] = owner_buf; -		columns[2]["font"] = "SANSSERIF"; - -		columns[3]["column"] = "location"; -		columns[3]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z); -		columns[3]["font"] = "SANSSERIF"; -		columns[4]["column"] = "time"; -		columns[4]["type"] = "date"; -		columns[4]["value"] = LLDate((time_t)time_stamp); -		columns[4]["font"] = "SANSSERIF"; +		columns[column_num]["column"] = "owner"; +		columns[column_num]["value"] = owner_buf; +		columns[column_num++]["font"] = "SANSSERIF"; + +		columns[column_num]["column"] = "location"; +		columns[column_num]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z); +		columns[column_num++]["font"] = "SANSSERIF"; + +		columns[column_num]["column"] = "parcel"; +		columns[column_num]["value"] = parcel_buf; +		columns[column_num++]["font"] = "SANSSERIF"; + +		columns[column_num]["column"] = "time"; +		columns[column_num]["type"] = "date"; +		columns[column_num]["value"] = LLDate((time_t)time_stamp); +		columns[column_num++]["font"] = "SANSSERIF";  		if (mCurrentMode == STAT_REPORT_TOP_SCRIPTS  			&& have_extended_data)  		{ -			columns[5]["column"] = "mono_time"; -			columns[5]["value"] = llformat("%0.3f", mono_score); -			columns[5]["font"] = "SANSSERIF"; +			columns[column_num]["column"] = "memory"; +			columns[column_num]["value"] = llformat("%0.0f", (script_memory / 1000.f)); +			columns[column_num++]["font"] = "SANSSERIF"; -			columns[6]["column"] = "URLs"; -			columns[6]["value"] = llformat("%d", public_urls); -			columns[6]["font"] = "SANSSERIF"; +			columns[column_num]["column"] = "URLs"; +			columns[column_num]["value"] = llformat("%d", public_urls); +			columns[column_num++]["font"] = "SANSSERIF";  		}  		element["columns"] = columns;  		list->addElement(element); @@ -260,18 +260,18 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)  	{  		setTitle(getString("top_scripts_title"));  		list->setColumnLabel("score", getString("scripts_score_label")); -		list->setColumnLabel("mono_time", getString("scripts_mono_time_label"));  		LLUIString format = getString("top_scripts_text");  		format.setArg("[COUNT]", llformat("%d", total_count)); -		format.setArg("[TIME]", llformat("%0.1f", mtotalScore)); +		format.setArg("[TIME]", llformat("%0.3f", mtotalScore));  		getChild<LLUICtrl>("title_text")->setValue(LLSD(format));  	}  	else  	{  		setTitle(getString("top_colliders_title"));  		list->setColumnLabel("score", getString("colliders_score_label")); -		list->setColumnLabel("mono_time", ""); +		list->setColumnLabel("URLs", ""); +		list->setColumnLabel("memory", "");  		LLUIString format = getString("top_colliders_text");  		format.setArg("[COUNT]", llformat("%d", total_count));  		getChild<LLUICtrl>("title_text")->setValue(LLSD(format)); @@ -301,6 +301,7 @@ void LLFloaterTopObjects::updateSelectionInfo()  	{  		getChild<LLUICtrl>("object_name_editor")->setValue(sli->getColumn(1)->getValue().asString());  		getChild<LLUICtrl>("owner_name_editor")->setValue(sli->getColumn(2)->getValue().asString()); +		getChild<LLUICtrl>("parcel_name_editor")->setValue(sli->getColumn(4)->getValue().asString());  	}  } @@ -480,6 +481,15 @@ void LLFloaterTopObjects::onGetByOwnerName()  	onRefresh();  } + +void LLFloaterTopObjects::onGetByParcelName() +{ +	mFlags  = STAT_FILTER_BY_PARCEL_NAME; +	mFilter = getChild<LLUICtrl>("parcel_name_editor")->getValue().asString(); +	onRefresh(); +} + +  void LLFloaterTopObjects::showBeacon()  {  	LLScrollListCtrl* list = getChild<LLScrollListCtrl>("objects_list"); diff --git a/indra/newview/llfloatertopobjects.h b/indra/newview/llfloatertopobjects.h index a608ca20f1..6edc46cf79 100644 --- a/indra/newview/llfloatertopobjects.h +++ b/indra/newview/llfloatertopobjects.h @@ -73,9 +73,7 @@ private:  	void onGetByOwnerName();  	void onGetByObjectName(); - -//	static void onGetByOwnerNameClicked(void* data)  { onGetByOwnerName(NULL, data); }; -//	static void onGetByObjectNameClicked(void* data) { onGetByObjectName(NULL, data); }; +	void onGetByParcelName();  	void showBeacon(); diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 1a17183efd..bb01ce5a7e 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -29,7 +29,7 @@  #include "llfloatertranslationsettings.h"  // Viewer includes -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "lltranslate.h"  #include "llviewercontrol.h" // for gSavedSettings @@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK()  	gSavedSettings.setString("TranslationService", getSelectedService());  	gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey());  	gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); -	LLNearbyChatBar::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +	LLNearbyChat::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured());  	closeFloater(false);  } diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp new file mode 100644 index 0000000000..87b388b30a --- /dev/null +++ b/indra/newview/llfloatervoicevolume.cpp @@ -0,0 +1,209 @@ +/**  + * @file llfloatervoicevolume.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatervoicevolume.h" + +// Linden libraries +#include "llavatarname.h" +#include "llavatarnamecache.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "lltextbox.h" + +// viewer files +#include "llagent.h" +#include "llavataractions.h" +#include "llinspect.h" +#include "lltransientfloatermgr.h" +#include "llvoiceclient.h" + +class LLAvatarName; + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolume +////////////////////////////////////////////////////////////////////////////// + +// Avatar Inspector, a small information window used when clicking +// on avatar names in the 2D UI and in the ambient inspector widget for +// the 3D world. +class LLFloaterVoiceVolume : public LLInspect, LLTransientFloater +{ +	friend class LLFloaterReg; +	 +public: +	// avatar_id - Avatar ID for which to show information +	// Inspector will be positioned relative to current mouse position +	LLFloaterVoiceVolume(const LLSD& avatar_id); +	virtual ~LLFloaterVoiceVolume(); +	 +	/*virtual*/ BOOL postBuild(void); +	 +	// Because floater is single instance, need to re-parse data on each spawn +	// (for example, inspector about same avatar but in different position) +	/*virtual*/ void onOpen(const LLSD& avatar_id); + +	/*virtual*/ LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; } + +private: +	// Set the volume slider to this user's current client-side volume setting, +	// hiding/disabling if the user is not nearby. +	void updateVolumeControls(); + +	void onClickMuteVolume(); +	void onVolumeChange(const LLSD& data); +	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); +	 +private: +	LLUUID				mAvatarID; +	// Need avatar name information to spawn friend add request +	LLAvatarName		mAvatarName; +}; + +LLFloaterVoiceVolume::LLFloaterVoiceVolume(const LLSD& sd) +:	LLInspect(LLSD())		// single_instance, doesn't really need key +,	mAvatarID()				// set in onOpen()  *Note: we used to show partner's name but we dont anymore --angela 3rd Dec* +,	mAvatarName() +{ +	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this); +	LLTransientFloater::init(this); +} + +LLFloaterVoiceVolume::~LLFloaterVoiceVolume() +{ +	LLTransientFloaterMgr::getInstance()->removeControlView(this); +} + +/*virtual*/ +BOOL LLFloaterVoiceVolume::postBuild(void) +{ +	getChild<LLUICtrl>("mute_btn")->setCommitCallback( +		boost::bind(&LLFloaterVoiceVolume::onClickMuteVolume, this) ); + +	getChild<LLUICtrl>("volume_slider")->setCommitCallback( +		boost::bind(&LLFloaterVoiceVolume::onVolumeChange, this, _2)); + +	return TRUE; +} + + +// Multiple calls to showInstance("floater_voice_volume", foo) will provide different +// LLSD for foo, which we will catch here. +//virtual +void LLFloaterVoiceVolume::onOpen(const LLSD& data) +{ +	// Start open animation +	LLInspect::onOpen(data); + +	// Extract appropriate avatar id +	mAvatarID = data["avatar_id"]; + +	LLUI::positionViewNearMouse(this); + +	getChild<LLUICtrl>("avatar_name")->setValue(""); +	updateVolumeControls(); + +	LLAvatarNameCache::get(mAvatarID, +		boost::bind(&LLFloaterVoiceVolume::onAvatarNameCache, this, _1, _2)); +} + +void LLFloaterVoiceVolume::updateVolumeControls() +{ +	bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); + +	LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); +	LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); + +	// Do not display volume slider and mute button if it  +	// is ourself or we are not in a voice channel together +	if (!voice_enabled || (mAvatarID == gAgent.getID())) +	{ +		mute_btn->setVisible(false); +		volume_slider->setVisible(false); +	} +	else  +	{ +		mute_btn->setVisible(true); +		volume_slider->setVisible(true); + +		// By convention, we only display and toggle voice mutes, not all mutes +		bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); +		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); + +		mute_btn->setEnabled(!is_linden); +		mute_btn->setValue(is_muted); + +		volume_slider->setEnabled(!is_muted); + +		F32 volume; +		if (is_muted) +		{ +			// it's clearer to display their volume as zero +			volume = 0.f; +		} +		else +		{ +			// actual volume +			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); +		} +		volume_slider->setValue((F64)volume); +	} + +} + +void LLFloaterVoiceVolume::onClickMuteVolume() +{ +	LLAvatarActions::toggleMuteVoice(mAvatarID); +	updateVolumeControls(); +} + +void LLFloaterVoiceVolume::onVolumeChange(const LLSD& data) +{ +	F32 volume = (F32)data.asReal(); +	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); +} + +void LLFloaterVoiceVolume::onAvatarNameCache( +		const LLUUID& agent_id, +		const LLAvatarName& av_name) +{ +	if (agent_id != mAvatarID) +	{ +		return; +	} + +	getChild<LLUICtrl>("avatar_name")->setValue(av_name.getCompleteName()); +	mAvatarName = av_name; +} + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolumeUtil +////////////////////////////////////////////////////////////////////////////// +void LLFloaterVoiceVolumeUtil::registerFloater() +{ +	LLFloaterReg::add("floater_voice_volume", "floater_voice_volume.xml", +					  &LLFloaterReg::build<LLFloaterVoiceVolume>); +} diff --git a/indra/newview/llfloatervoicevolume.h b/indra/newview/llfloatervoicevolume.h new file mode 100644 index 0000000000..8fcf7f250b --- /dev/null +++ b/indra/newview/llfloatervoicevolume.h @@ -0,0 +1,35 @@ +/**  + * @file llfloatervoicevolume.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERVOICEVOLUME_H +#define LL_LLFLOATERVOICEVOLUME_H + +namespace LLFloaterVoiceVolumeUtil +{ +	// Register with LLFloaterReg +	void registerFloater(); +} + +#endif // LL_LLFLOATERVOICEVOLUME_H diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h deleted file mode 100644 index 06682dcbf1..0000000000 --- a/indra/newview/llfoldervieweventlistener.h +++ /dev/null @@ -1,103 +0,0 @@ -/**  - * @file llfoldervieweventlistener.h - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ -#ifndef LLFOLDERVIEWEVENTLISTENER_H -#define LLFOLDERVIEWEVENTLISTENER_H - -#include "lldarray.h"	// *TODO: convert to std::vector -#include "llfoldertype.h" -#include "llfontgl.h"	// just for StyleFlags enum -#include "llinventorytype.h" -#include "llpermissionsflags.h" -#include "llpointer.h" -#include "llwearabletype.h" - - -class LLFolderViewItem; -class LLFolderView; -class LLFontGL; -class LLInventoryModel; -class LLMenuGL; -class LLScrollContainer; -class LLUIImage; -class LLUUID; - -// This is an abstract base class that users of the folderview classes -// would use to catch the useful events emitted from the folder -// views. -class LLFolderViewEventListener -{ -public: -	virtual ~LLFolderViewEventListener( void ) {} -	virtual const std::string& getName() const = 0; -	virtual const std::string& getDisplayName() const = 0; -	virtual const LLUUID& getUUID() const = 0; -	virtual time_t getCreationDate() const = 0;	// UTC seconds -	virtual PermissionMask getPermissionMask() const = 0; -	virtual LLFolderType::EType getPreferredType() const = 0; -	virtual LLPointer<LLUIImage> getIcon() const = 0; -	virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } -	virtual LLFontGL::StyleFlags getLabelStyle() const = 0; -	virtual std::string getLabelSuffix() const = 0; -	virtual void openItem( void ) = 0; -	virtual void closeItem( void ) = 0; -	virtual void previewItem( void ) = 0; -	virtual void selectItem(void) = 0; -	virtual void showProperties(void) = 0; -	virtual BOOL isItemRenameable() const = 0; -	virtual BOOL renameItem(const std::string& new_name) = 0; -	virtual BOOL isItemMovable( void ) const = 0;		// Can be moved to another folder -	virtual BOOL isItemRemovable( void ) const = 0;		// Can be destroyed -	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. -	virtual BOOL removeItem() = 0; -	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0; -	virtual void move( LLFolderViewEventListener* parent_listener ) = 0; -	virtual BOOL isItemCopyable() const = 0; -	virtual BOOL copyToClipboard() const = 0; -	virtual BOOL cutToClipboard() const = 0; -	virtual BOOL isClipboardPasteable() const = 0; -	virtual void pasteFromClipboard() = 0; -	virtual void pasteLinkFromClipboard() = 0; -	virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; -	virtual BOOL isUpToDate() const = 0; -	virtual BOOL hasChildren() const = 0; -	virtual LLInventoryType::EType getInventoryType() const = 0; -	virtual void performAction(LLInventoryModel* model, std::string action) = 0; -	virtual LLWearableType::EType getWearableType() const = 0; -	 -	// This method should be called when a drag begins. returns TRUE -	// if the drag can begin, otherwise FALSE. -	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; -	 -	// This method will be called to determine if a drop can be -	// performed, and will set drop to TRUE if a drop is -	// requested. Returns TRUE if a drop is possible/happened, -	// otherwise FALSE. -	virtual BOOL dragOrDrop(MASK mask, BOOL drop, -							EDragAndDropType cargo_type, -							void* cargo_data, -							std::string& tooltip_msg) = 0; -}; - -#endif diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp new file mode 100644 index 0000000000..8a4b4bae84 --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -0,0 +1,322 @@ +/*  + * @file llfolderviewmodelinventory.cpp + * @brief Implementation of the inventory-specific view model + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfolderviewmodelinventory.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventorypanel.h" +#include "lltooldraganddrop.h" + +// +// class LLFolderViewModelInventory +// +static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); + +bool LLFolderViewModelInventory::startDrag(std::vector<LLFolderViewModelItem*>& items) +{ +	std::vector<EDragAndDropType> types; +	uuid_vec_t cargo_ids; +	std::vector<LLFolderViewModelItem*>::iterator item_it; +	bool can_drag = true; +	if (!items.empty()) +	{ +		for (item_it = items.begin(); item_it != items.end(); ++item_it) +		{ +			EDragAndDropType type = DAD_NONE; +			LLUUID id = LLUUID::null; +			can_drag = can_drag && static_cast<LLFolderViewModelItemInventory*>(*item_it)->startDrag(&type, &id); + +			types.push_back(type); +			cargo_ids.push_back(id); +		} + +		LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids,  +			static_cast<LLFolderViewModelItemInventory*>(items.front())->getDragSource(), mTaskID);  +	} +	return can_drag; +} + + +void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) +{ +	LLFastTimer _(FTM_INVENTORY_SORT); + +	if (!needsSort(folder->getViewModelItem())) return; + +	LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); +	if (modelp->getUUID().isNull()) return; + +	for (std::list<LLFolderViewFolder*>::iterator it =   folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); +		it != end_it; +		++it) +	{ +		LLFolderViewFolder* child_folderp = *it; +		sort(child_folderp); + +		if (child_folderp->getFoldersCount() > 0) +		{ +			time_t most_recent_folder_time = +				static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); +			LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); +			if (most_recent_folder_time > modelp->getCreationDate()) +			{ +				modelp->setCreationDate(most_recent_folder_time); +			} +		} +		if (child_folderp->getItemsCount() > 0)			 +		{ +			time_t most_recent_item_time = +				static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); + +			LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); +			if (most_recent_item_time > modelp->getCreationDate()) +			{ +				modelp->setCreationDate(most_recent_item_time); +			} +		} +	} +	base_t::sort(folder); +} + +bool LLFolderViewModelInventory::contentsReady() +{ +	return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); +} + +void LLFolderViewModelItemInventory::requestSort() +{ +	LLFolderViewModelItemCommon::requestSort(); +	LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(mFolderViewItem); +	if (folderp) +	{ +		folderp->requestArrange(); +	} +	if (static_cast<LLFolderViewModelInventory&>(mRootViewModel).getSorter().isByDate()) +	{ +		// sort by date potentially affects parent folders which use a date +		// derived from newest item in them +		if (mParent) +		{ +			mParent->requestSort(); +		} +	} +} + +void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size) +{ +	LLFolderViewModelItemCommon::setPassedFilter(passed, filter_generation, string_offset, string_size); + +	bool passed_filter_before = mPrevPassedAllFilters; +	mPrevPassedAllFilters = passedFilter(filter_generation); + +	if (passed_filter_before != mPrevPassedAllFilters) +	{ +		//TODO RN: ensure this still happens, but without dependency on folderview +		LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); +		if (parent_folder) +		{ +			parent_folder->requestArrange(); +		} +	} +} + +bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +{ +	S32 filter_generation = filter.getCurrentGeneration(); + +	bool continue_filtering = true; +	if (item->getLastFilterGeneration() < filter_generation) +	{ +		// recursive application of the filter for child items +		continue_filtering = item->filter( filter ); +	} + +	// track latest generation to pass any child items, for each folder up to root +	if (item->passedFilter()) +	{ +		LLFolderViewModelItemInventory* view_model = this; +		 +		while(view_model && view_model->mMostFilteredDescendantGeneration < filter_generation) +		{ +			view_model->mMostFilteredDescendantGeneration = filter_generation; +			view_model = static_cast<LLFolderViewModelItemInventory*>(view_model->mParent); +		} +	} + +	return continue_filtering; +} + +bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +{ +	const S32 filter_generation = filter.getCurrentGeneration(); +	const S32 must_pass_generation = filter.getFirstRequiredGeneration(); + +	if (getLastFilterGeneration() >= must_pass_generation  +		&& getLastFolderFilterGeneration() >= must_pass_generation +		&& !passedFilter(must_pass_generation)) +	{ +		// failed to pass an earlier filter that was a subset of the current one +		// go ahead and flag this item as done +		setPassedFilter(false, filter_generation); +		setPassedFolderFilter(false, filter_generation); +		return true; +	} + +	const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY)  +		? filter.checkFolder(this) +		: true; +	setPassedFolderFilter(passed_filter_folder, filter_generation); + +	if(!mChildren.empty() +		&& (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass +			|| descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement +	{ +		// now query children +		for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); +			iter != end_iter && filter.getFilterCount() > 0; +			++iter) +		{ +			if (!filterChildItem((*iter), filter)) +			{ +				break; +			} +		} +	} + +	// if we didn't use all filter iterations +	// that means we filtered all of our descendants +	// so filter ourselves now +	if (filter.getFilterCount() > 0) +	{ +		filter.decrementFilterCount(); + +		const bool passed_filter = filter.check(this); +		setPassedFilter(passed_filter, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize()); +		return true; +	} +	else +	{ +		return false; +	} +} + +LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() +{ +	return &mInventoryViewModel; +} + + +const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const +{ +	return &mInventoryViewModel; +} + +bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const +{ +	// ignore sort order for landmarks in the Favorites folder. +	// they should be always sorted as in Favorites bar. See EXT-719 +	//TODO RN: fix sorting in favorites folder +	//if (a->getSortGroup() == SG_ITEM +	//	&& b->getSortGroup() == SG_ITEM +	//	&& a->getInventoryType() == LLInventoryType::IT_LANDMARK +	//	&& b->getInventoryType() == LLInventoryType::IT_LANDMARK) +	//{ + +	//	static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + +	//	LLUUID a_uuid = a->getParentFolder()->getUUID(); +	//	LLUUID b_uuid = b->getParentFolder()->getUUID(); + +	//	if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) +	//	{ +	//		// *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem +	//		// or to LLInvFVBridge +	//		LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); +	//		LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); +	//		if (!aitem || !bitem) +	//			return false; +	//		S32 a_sort = aitem->getSortField(); +	//		S32 b_sort = bitem->getSortField(); +	//		return a_sort < b_sort; +	//	} +	//} + +	// We sort by name if we aren't sorting by date +	// OR if these are folders and we are sorting folders by name. +	bool by_name = (!mByDate  +		|| (mFoldersByName  +		&& (a->getSortGroup() != SG_ITEM))); + +	if (a->getSortGroup() != b->getSortGroup()) +	{ +		if (mSystemToTop) +		{ +			// Group order is System Folders, Trash, Normal Folders, Items +			return (a->getSortGroup() < b->getSortGroup()); +		} +		else if (mByDate) +		{ +			// Trash needs to go to the bottom if we are sorting by date +			if ( (a->getSortGroup() == SG_TRASH_FOLDER) +				|| (b->getSortGroup() == SG_TRASH_FOLDER)) +			{ +				return (b->getSortGroup() == SG_TRASH_FOLDER); +			} +		} +	} + +	if (by_name) +	{ +		S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); +		if (0 == compare) +		{ +			return (a->getCreationDate() > b->getCreationDate()); +		} +		else +		{ +			return (compare < 0); +		} +	} +	else +	{ +		time_t first_create = a->getCreationDate(); +		time_t second_create = b->getCreationDate(); +		if (first_create == second_create) +		{ +			return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0); +		} +		else +		{ +			return (first_create > second_create); +		} +	} +} + +LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model )  +	:	LLFolderViewModelItemCommon(root_view_model), +	mPrevPassedAllFilters(false) +{ +} diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h new file mode 100644 index 0000000000..890d03d1c9 --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.h @@ -0,0 +1,118 @@ +/**  + * @file llfolderviewmodelinventory.h + * @brief view model implementation specific to inventory + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFOLDERVIEWMODELINVENTORY_H +#define LL_LLFOLDERVIEWMODELINVENTORY_H + +#include "llinventoryfilter.h" +#include "llinventory.h" +#include "llwearabletype.h" +#include "lltooldraganddrop.h" + +class LLFolderViewModelItemInventory +	:	public LLFolderViewModelItemCommon +{ +public: +	LLFolderViewModelItemInventory(class LLFolderViewModelInventory& root_view_model); +	virtual const LLUUID& getUUID() const = 0; +	virtual time_t getCreationDate() const = 0;	// UTC seconds +	virtual void setCreationDate(time_t creation_date_utc) = 0; +	virtual PermissionMask getPermissionMask() const = 0; +	virtual LLFolderType::EType getPreferredType() const = 0; +	virtual void showProperties(void) = 0; +	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make   into pure virtual. +	virtual BOOL isUpToDate() const = 0; +	virtual bool hasChildren() const = 0; +	virtual LLInventoryType::EType getInventoryType() const = 0; +	virtual void performAction(LLInventoryModel* model, std::string action)   = 0; +	virtual LLWearableType::EType getWearableType() const = 0; +	virtual EInventorySortGroup getSortGroup() const = 0; +	virtual LLInventoryObject* getInventoryObject() const = 0; +	virtual void requestSort(); +	virtual void setPassedFilter(bool filtered, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0); +	virtual bool filter( LLFolderViewFilter& filter); +	virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); + +	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; +	virtual LLToolDragAndDrop::ESource getDragSource() const = 0; + +protected: +	bool								mPrevPassedAllFilters; +}; + +class LLInventorySort +{ +public: +	struct Params : public LLInitParam::Block<Params> +	{ +		Optional<S32> order; + +		Params() +		:	order("order", 0) +		{} +	}; + +	LLInventorySort(S32 order = 0) +	{ +		fromParams(Params().order(order)); +	} + +	bool isByDate() const { return mByDate; } +	U32 getSortOrder() const { return mSortOrder; } +	void toParams(Params& p) { p.order(mSortOrder);} +	void fromParams(Params& p)  +	{  +		mSortOrder = p.order;  +		mByDate = (mSortOrder & LLInventoryFilter::SO_DATE); +		mSystemToTop = (mSortOrder & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); +		mFoldersByName = (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME); +	} + +	bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; +private: +	U32  mSortOrder; +	bool mByDate; +	bool mSystemToTop; +	bool mFoldersByName; +}; + +class LLFolderViewModelInventory +	:	public LLFolderViewModel<LLInventorySort,   LLFolderViewModelItemInventory, LLFolderViewModelItemInventory,   LLInventoryFilter> +{ +public: +	typedef LLFolderViewModel<LLInventorySort,   LLFolderViewModelItemInventory, LLFolderViewModelItemInventory,   LLInventoryFilter> base_t; + +	void setTaskID(const LLUUID& id) {mTaskID = id;} + +	void sort(LLFolderViewFolder* folder); +	bool contentsReady(); +	bool startDrag(std::vector<LLFolderViewModelItem*>& items); + +private: +	LLUUID mTaskID; +}; +#endif // LL_LLFOLDERVIEWMODELINVENTORY_H diff --git a/indra/newview/llfollowcam.cpp b/indra/newview/llfollowcam.cpp index b670af1782..47612fe25c 100644 --- a/indra/newview/llfollowcam.cpp +++ b/indra/newview/llfollowcam.cpp @@ -38,7 +38,6 @@ std::vector<LLFollowCamParams*> LLFollowCamMgr::sParamStack;  //-------------------------------------------------------  // constants  //------------------------------------------------------- -const F32 ONE_HALF							= 0.5;   const F32 FOLLOW_CAM_ZOOM_FACTOR			= 0.1f;  const F32 FOLLOW_CAM_MIN_ZOOM_AMOUNT		= 0.1f;  const F32 DISTANCE_EPSILON					= 0.0001f; diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 11401d6c68..a64ddd185d 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -47,13 +47,13 @@ static const std::string INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER = "All";  // helper functions  // NOTE: For now Friends & All folders are created as protected folders of the LLFolderType::FT_CALLINGCARD type. -// So, their names will be processed in the LLFolderViewItem::refreshFromListener() to be localized +// So, their names will be processed in the LLFolderViewItem::refresh() to be localized  // using "InvFolder LABEL_NAME" as LLTrans::findString argument.  // We must use in this file their hard-coded names to ensure found them on different locales. EXT-5829.  // These hard-coded names will be stored in InventoryItems but shown localized in FolderViewItems -// If hack in the LLFolderViewItem::refreshFromListener() to localize protected folder is removed +// If hack in the LLFolderViewItem::refresh() to localize protected folder is removed  // or these folders are not protected these names should be localized in another place/way.  inline const std::string get_friend_folder_name()  { diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 66ca76bfb0..26b63bdacb 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -51,7 +51,7 @@  #include "llviewermessage.h"  #include "llvoavatarself.h"  #include "llviewerstats.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llappearancemgr.h"  #include "llgesturelistener.h" @@ -997,7 +997,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step)  			const BOOL animate = FALSE; -			LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); +			LLNearbyChat::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);  			gesture->mCurrentStep++;  			break; diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 129cddda45..aba3d74d87 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -86,7 +86,7 @@ LLGroupList::LLGroupList(const Params& p)  	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", +	LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups.xml",  			gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());  	if(context_menu)  		mContextMenuHandle = context_menu->getHandle(); @@ -112,7 +112,7 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); -	LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get(); +	LLToggleableMenu* context_menu = mContextMenuHandle.get();  	if (context_menu && size() > 0)  	{  		context_menu->buildDrawLabels(); @@ -406,7 +406,7 @@ void LLGroupListItem::setActive(bool active)  	// *BUG: setName() overrides the style params.  	// Active group should be bold. -	LLFontDescriptor new_desc(mGroupNameBox->getDefaultFont()->getFontDesc()); +	LLFontDescriptor new_desc(mGroupNameBox->getFont()->getFontDesc());  	// *NOTE dzaporozhan  	// On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font  diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 8abf14b3d0..e96a720886 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -28,10 +28,13 @@  #define LL_LLGROUPLIST_H  #include "llevent.h" +#include "llpointer.h" +  #include "llflatlistview.h"  #include "llpanel.h" -#include "llpointer.h"  #include "llstyle.h" +#include "lltoggleablemenu.h" +  #include "llgroupmgr.h"  /** @@ -45,6 +48,10 @@ class LLGroupList: public LLFlatListViewEx, public LLOldEvents::LLSimpleListener  {  	LOG_CLASS(LLGroupList);  public: +	struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> +	{ +		Params(){}; +	};  	LLGroupList(const Params& p);  	virtual ~LLGroupList(); @@ -57,6 +64,8 @@ public:  	void toggleIcons();  	bool getIconsVisible() const { return mShowIcons; } +	LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); } +  private:  	void setDirty(bool val = true)		{ mDirty = val; }  	void refresh(); @@ -66,7 +75,7 @@ private:  	bool onContextMenuItemClick(const LLSD& userdata);  	bool onContextMenuItemEnable(const LLSD& userdata); -	LLHandle<LLView>	mContextMenuHandle; +	LLHandle<LLToggleableMenu>	mContextMenuHandle;  	bool mShowIcons;  	bool mDirty; diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index efffd0f98e..aceb7f0614 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -63,7 +63,7 @@  #pragma warning(pop)   // Restore all warnings to the previous state  #endif -const U32 MAX_CACHED_GROUPS = 10; +const U32 MAX_CACHED_GROUPS = 20;  //  // LLRoleActionSet @@ -234,10 +234,16 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) :  	mRoleDataComplete(FALSE),  	mRoleMemberDataComplete(FALSE),  	mGroupPropertiesDataComplete(FALSE), -	mPendingRoleMemberRequest(FALSE) +	mPendingRoleMemberRequest(FALSE), +	mAccessTime(0.0f)  {  } +void LLGroupMgrGroupData::setAccessed() +{ +	mAccessTime = (F32)LLFrameTimer::getTotalSeconds(); +} +  BOOL LLGroupMgrGroupData::getRoleData(const LLUUID& role_id, LLRoleData& role_data)  {  	role_data_map_t::const_iterator it; @@ -1360,7 +1366,7 @@ void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data)  LLGroupMgrGroupData* LLGroupMgr::createGroupData(const LLUUID& id)  { -	LLGroupMgrGroupData* group_datap; +	LLGroupMgrGroupData* group_datap = NULL;  	group_map_t::iterator existing_group = LLGroupMgr::getInstance()->mGroups.find(id);  	if (existing_group == LLGroupMgr::getInstance()->mGroups.end()) @@ -1373,6 +1379,11 @@ LLGroupMgrGroupData* LLGroupMgr::createGroupData(const LLUUID& id)  		group_datap = existing_group->second;  	} +	if (group_datap) +	{ +		group_datap->setAccessed(); +	} +  	return group_datap;  } @@ -1413,25 +1424,41 @@ void LLGroupMgr::notifyObservers(LLGroupChange gc)  void LLGroupMgr::addGroup(LLGroupMgrGroupData* group_datap)  { -	if (mGroups.size() > MAX_CACHED_GROUPS) +	while (mGroups.size() >= MAX_CACHED_GROUPS)  	{ -		// get rid of groups that aren't observed -		for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end() && mGroups.size() > MAX_CACHED_GROUPS / 2; ) +		// LRU: Remove the oldest un-observed group from cache until group size is small enough + +		F32 oldest_access = LLFrameTimer::getTotalSeconds(); +		group_map_t::iterator oldest_gi = mGroups.end(); + +		for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end(); ++gi )  		{  			observer_multimap_t::iterator oi = mObservers.find(gi->first);  			if (oi == mObservers.end())  			{ -				// not observed -				LLGroupMgrGroupData* unobserved_groupp = gi->second; -				delete unobserved_groupp; -				mGroups.erase(gi++); -			} -			else -			{ -				++gi; +				if (gi->second  +						&& (gi->second->getAccessTime() < oldest_access)) +				{ +					oldest_access = gi->second->getAccessTime(); +					oldest_gi = gi; +				}  			}  		} +		 +		if (oldest_gi != mGroups.end()) +		{ +			delete oldest_gi->second; +			mGroups.erase(oldest_gi); +		} +		else +		{ +			// All groups must be currently open, none to remove. +			// Just add the new group anyway, but get out of this loop as it  +			// will never drop below max_cached_groups. +			break; +		}  	} +  	mGroups[group_datap->getID()] = group_datap;  } diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index faf0531c10..df3cd17e03 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -86,7 +86,7 @@ public:  	BOOL isInRole(const LLUUID& role_id) { return (mRolesList.find(role_id) != mRolesList.end()); } -protected: +private:  	LLUUID	mID;  	S32		mContribution;  	U64		mAgentPowers; @@ -233,6 +233,9 @@ public:  	BOOL isRoleMemberDataComplete() { return mRoleMemberDataComplete; }  	BOOL isGroupPropertiesDataComplete() { return mGroupPropertiesDataComplete; } +	F32 getAccessTime() const { return mAccessTime; } +	void setAccessed(); +  public:  	typedef	std::map<LLUUID,LLGroupMemberData*> member_list_t;  	typedef	std::map<LLUUID,LLGroupRoleData*> role_list_t; @@ -280,6 +283,7 @@ private:  	BOOL				mGroupPropertiesDataComplete;  	BOOL				mPendingRoleMemberRequest; +	F32					mAccessTime;  };  struct LLRoleAction diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 482294c8a6..3336097955 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -166,7 +166,6 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3&  	}  	// scale screen size of borders down -	//RN: for now, text on hud objects is never occluded  	LLVector3 x_pixel_vec;  	LLVector3 y_pixel_vec; @@ -187,45 +186,29 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3&  			+ (y_pixel_vec * screen_offset.mV[VY]); -	//if (mUseBubble) +	LLVector3 bg_pos = render_position +		+ (F32)mOffsetY * y_pixel_vec +		- (width_vec / 2.f) +		- (height_vec); + +	LLVector3 v[] =   	{ -		LLVector3 bg_pos = render_position -			+ (F32)mOffsetY * y_pixel_vec -			- (width_vec / 2.f) -			- (height_vec); -		//LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); +		bg_pos, +		bg_pos + width_vec, +		bg_pos + width_vec + height_vec, +		bg_pos + height_vec, +	}; -		LLVector3 v[] =  -		{ -			bg_pos, -			bg_pos + width_vec, -			bg_pos + width_vec + height_vec, -			bg_pos + height_vec, -		}; +	LLVector3 dir = end-start; +	F32 a, b, t; -		if (debug_render) +	if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || +		LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) +	{ +		if (t <= 1.f)  		{ -			gGL.begin(LLRender::LINE_STRIP); -			gGL.vertex3fv(v[0].mV); -			gGL.vertex3fv(v[1].mV); -			gGL.vertex3fv(v[2].mV); -			gGL.vertex3fv(v[3].mV); -			gGL.vertex3fv(v[0].mV); -			gGL.vertex3fv(v[2].mV); -			gGL.end(); -		} - -		LLVector3 dir = end-start; -		F32 a, b, t; - -		if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || -			LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) -		{ -			if (t <= 1.f) -			{ -				intersection = start + dir*t; -				return TRUE; -			} +			intersection = start + dir*t; +			return TRUE;  		}  	} @@ -241,12 +224,6 @@ void LLHUDNameTag::render()  	}  } -void LLHUDNameTag::renderForSelect() -{ -	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); -	renderText(TRUE); -} -  void LLHUDNameTag::renderText(BOOL for_select)  {  	if (!mVisible || mHidden) @@ -299,24 +276,6 @@ void LLHUDNameTag::renderText(BOOL for_select)  	LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground");  	bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); -	// maybe a no-op? -	//const S32 border_height = 16; -	//const S32 border_width = 16; -	const S32 border_height = 8; -	const S32 border_width = 8; - -	// *TODO move this into helper function -	F32 border_scale = 1.f; - -	if (border_height * 2 > mHeight) -	{ -		border_scale = (F32)mHeight / ((F32)border_height * 2.f); -	} -	if (border_width * 2 > mWidth) -	{ -		border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f)); -	} -  	// scale screen size of borders down  	//RN: for now, text on hud objects is never occluded @@ -325,152 +284,34 @@ void LLHUDNameTag::renderText(BOOL for_select)  	LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); -	LLVector2 border_scale_vec((F32)border_width / (F32)imagep->getTextureWidth(), (F32)border_height / (F32)imagep->getTextureHeight());  	LLVector3 width_vec = mWidth * x_pixel_vec;  	LLVector3 height_vec = mHeight * y_pixel_vec; -	LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec; -	LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec;  	mRadius = (width_vec + height_vec).magVec() * 0.5f;  	LLCoordGL screen_pos;  	LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); -	LLVector2 screen_offset; -//	if (!mUseBubble) -//	{ -//		screen_offset = mPositionOffset; -//	} -//	else -//	{ -		screen_offset = updateScreenPos(mPositionOffset); -//	} +	LLVector2 screen_offset = updateScreenPos(mPositionOffset);  	LLVector3 render_position = mPositionAgent    			+ (x_pixel_vec * screen_offset.mV[VX])  			+ (y_pixel_vec * screen_offset.mV[VY]); -//	if (mUseBubble) +	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); +	LLRect screen_rect; +	screen_rect.setCenterAndSize(0, static_cast<S32>(lltrunc(-mHeight / 2 + mOffsetY)), static_cast<S32>(lltrunc(mWidth)), static_cast<S32>(lltrunc(mHeight))); +	imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); +	if (mLabelSegments.size())  	{ -		LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); -		LLUI::pushMatrix(); -		{ -			LLVector3 bg_pos = render_position -				+ (F32)mOffsetY * y_pixel_vec -				- (width_vec / 2.f) -				- (height_vec); -			LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - -			if (for_select) -			{ -				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -				S32 name = mSourceObject->mGLName; -				LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); -				gGL.color4ubv(coloru.mV); -				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); -				LLUI::popMatrix(); -				return; -			} -			else -			{ -				gGL.getTexUnit(0)->bind(imagep->getImage()); -				 -				gGL.color4fv(bg_color.mV); -				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); -		 -				if ( mLabelSegments.size()) -				{ -					LLUI::pushMatrix(); -					{ -						gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); -						LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; -						LLVector3 label_offset = height_vec - label_height; -						LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); -						gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); -					} -					LLUI::popMatrix(); -				} -			} - -			BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; -			BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); +		LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top"); +		LLRect label_top_rect = screen_rect; +		const S32 label_height = llround((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f))); +		label_top_rect.mBottom = label_top_rect.mTop - label_height; +		LLColor4 label_top_color = text_color; +		label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; -			// draw line segments pointing to parent object -			if (!mOffscreen && (outside_width || outside_height)) -			{ -				LLUI::pushMatrix(); -				{ -					gGL.color4fv(bg_color.mV); -					LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec); -					target_pos += (width_vec / 2.f); -					target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero; -					target_pos -= 3.f * x_pixel_vec; -					target_pos -= 6.f * y_pixel_vec; -					LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]); -					gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec);	 -				} -				LLUI::popMatrix(); - -				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -				LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); -				 -				LLVector3 box_center_offset; -				box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); -				LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); -				gGL.color4fv(bg_color.mV); -				LLUI::setLineWidth(2.0); -				gGL.begin(LLRender::LINES); -				{ -					if (outside_width) -					{ -						LLVector3 vert; -						// draw line in x then y -						if (mPositionOffset.mV[VX] < 0.f) -						{ -							// start at right edge -							vert = width_vec * 0.5f; -							gGL.vertex3fv(vert.mV); -						} -						else -						{ -							// start at left edge -							vert = width_vec * -0.5f; -							gGL.vertex3fv(vert.mV); -						} -						vert = -mPositionOffset.mV[VX] * x_pixel_vec; -						gGL.vertex3fv(vert.mV); -						gGL.vertex3fv(vert.mV); -						vert -= mPositionOffset.mV[VY] * y_pixel_vec; -						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); -						gGL.vertex3fv(vert.mV); -					} -					else -					{ -						LLVector3 vert; -						// draw line in y then x -						if (mPositionOffset.mV[VY] < 0.f) -						{ -							// start at top edge -							vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); -							gGL.vertex3fv(vert.mV); -						} -						else -						{ -							// start at bottom edge -							vert = (height_vec * -0.5f)  - (mPositionOffset.mV[VX] * x_pixel_vec); -							gGL.vertex3fv(vert.mV); -						} -						vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; -						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); -						gGL.vertex3fv(vert.mV); -					} -				} -				gGL.end(); -				LLUI::setLineWidth(1.0); - -			} -		} -		LLUI::popMatrix(); +		rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color);  	}  	F32 y_offset = (F32)mOffsetY; @@ -874,29 +715,26 @@ void LLHUDNameTag::updateAll()  	for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)  	{  		LLHUDNameTag* textp = (*r_it); -//		if (textp->mUseBubble) -//		{ -			if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) -			{ -				textp->setLOD(3); -			} -			else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) -			{ -				textp->setLOD(2); -			} -			else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) -			{ -				textp->setLOD(1); -			} -			else -			{ -				textp->setLOD(0); -			} -			textp->updateSize(); -			// find on-screen position and initialize collision rectangle -			textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); -			current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); -//		} +		if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) +		{ +			textp->setLOD(3); +		} +		else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) +		{ +			textp->setLOD(2); +		} +		else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) +		{ +			textp->setLOD(1); +		} +		else +		{ +			textp->setLOD(0); +		} +		textp->updateSize(); +		// find on-screen position and initialize collision rectangle +		textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); +		current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight());  	}  	LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat(); @@ -914,20 +752,12 @@ void LLHUDNameTag::updateAll()  		{  			LLHUDNameTag* src_textp = (*src_it); -//			if (!src_textp->mUseBubble) -//			{ -//				continue; -//			}  			VisibleTextObjectIterator dst_it = src_it;  			++dst_it;  			for (; dst_it != sVisibleTextObjects.end(); ++dst_it)  			{  				LLHUDNameTag* dst_textp = (*dst_it); -//				if (!dst_textp->mUseBubble) -//				{ -//					continue; -//				}  				if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))  				{  					LLRectf intersect_rect = src_textp->mSoftScreenRect; @@ -976,10 +806,6 @@ void LLHUDNameTag::updateAll()  	VisibleTextObjectIterator this_object_it;  	for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it)  	{ -//		if (!(*this_object_it)->mUseBubble) -//		{ -//			continue; -//		}  		(*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC));  	}  } @@ -1037,10 +863,6 @@ void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list)  	VisibleTextObjectIterator text_it;  	for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it)  	{ -//		if (!(*text_it)->mUseBubble) -//		{ -//			continue; -//		}  		pick_list.insert((*text_it)->mSourceObject);  	}  } diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index 3325c22def..72647d5b26 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -118,7 +118,6 @@ public:  	/*virtual*/ void markDead();  	friend class LLHUDObject;  	/*virtual*/ F32 getDistance() const { return mLastDistance; } -	//void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; }  	S32  getLOD() { return mLOD; }  	BOOL getVisible() { return mVisible; }  	BOOL getHidden() const { return mHidden; } @@ -136,7 +135,6 @@ protected:  	LLHUDNameTag(const U8 type);  	/*virtual*/ void render(); -	/*virtual*/ void renderForSelect();  	void renderText(BOOL for_select);  	static void updateAll();  	void setLOD(S32 lod); diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index 95d57d08d8..0960846510 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -232,9 +232,11 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type)  	case LL_HUD_EFFECT_LOOKAT:  		hud_objectp = new LLHUDEffectLookAt(type);  		break; +#ifdef XXX_STINSON_CHUI_REWORK  	case LL_HUD_EFFECT_VOICE_VISUALIZER:  		hud_objectp = new LLVoiceVisualizer(type);  		break; +#endif // XXX_STINSON_CHUI_REWORK  	case LL_HUD_EFFECT_POINTAT:  		hud_objectp = new LLHUDEffectPointAt(type);  		break; diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 2f7a98c86c..32cffe6839 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -39,6 +39,8 @@  #include "lldrawpool.h"		// TODO: eliminate, unused below  #include <list> +#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot +  class LLViewerCamera;  class LLFontGL;  class LLFace; @@ -94,7 +96,9 @@ public:  		LL_HUD_EFFECT_EDIT,  		LL_HUD_EFFECT_LOOKAT,  		LL_HUD_EFFECT_POINTAT, +#ifdef XXX_STINSON_CHUI_REWORK  		LL_HUD_EFFECT_VOICE_VISUALIZER,	// Ventrella +#endif // XXX_STINSON_CHUI_REWORK  		LL_HUD_NAME_TAG,  		LL_HUD_EFFECT_BLOB  	}; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp new file mode 100644 index 0000000000..ee7f58b01f --- /dev/null +++ b/indra/newview/llimconversation.cpp @@ -0,0 +1,421 @@ +/** + * @file llimconversation.cpp + * @brief LLIMConversation class implements the common behavior of LNearbyChatBar + * @brief and LLIMFloater for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llimconversation.h" + +#include "llchatentry.h" +#include "llchathistory.h" +#include "lldraghandle.h" +#include "llfloaterreg.h" +#include "llimfloater.h" +#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container +#include "lllayoutstack.h" +#include "llnearbychat.h" + +const F32 REFRESH_INTERVAL = 0.2f; + +LLIMConversation::LLIMConversation(const LLUUID& session_id) +  : LLTransientDockableFloater(NULL, true, session_id) +  ,  mIsP2PChat(false) +  ,  mExpandCollapseBtn(NULL) +  ,  mTearOffBtn(NULL) +  ,  mCloseBtn(NULL) +  ,  mSessionID(session_id) +  , mParticipantList(NULL) +  , mChatHistory(NULL) +  , mInputEditor(NULL) +  , mInputEditorTopPad(0) +  , mRefreshTimer(new LLTimer()) +{ +	mCommitCallbackRegistrar.add("IMSession.Menu.Action", +			boost::bind(&LLIMConversation::onIMSessionMenuItemClicked,  this, _2)); +	mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", +			boost::bind(&LLIMConversation::onIMCompactExpandedMenuItemCheck, this, _2)); +	mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", +			boost::bind(&LLIMConversation::onIMShowModesMenuItemCheck,   this, _2)); +	mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", +			boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable,  this, _2)); + +	// Zero expiry time is set only once to allow initial update. +	mRefreshTimer->setTimerExpirySec(0); +	mRefreshTimer->start(); +} + +LLIMConversation::~LLIMConversation() +{ +	if (mParticipantList) +	{ +		delete mParticipantList; +		mParticipantList = NULL; +	} + +	delete mRefreshTimer; +} + +//static +LLIMConversation* LLIMConversation::findConversation(const LLUUID& uuid) +{ +    return LLFloaterReg::findTypedInstance<LLIMConversation>(uuid.isNull()? "chat_bar" : "impanel", LLSD(uuid)); +}; + +//static +LLIMConversation* LLIMConversation::getConversation(const LLUUID& uuid) +{ +	return LLFloaterReg::getTypedInstance<LLIMConversation>(uuid.isNull()? "chat_bar" : "impanel", LLSD(uuid)); +}; + + +BOOL LLIMConversation::postBuild() +{ +	BOOL result; + +	mCloseBtn = getChild<LLButton>("close_btn"); +	mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); + +	mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); +	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); + +	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); + +	mTearOffBtn = getChild<LLButton>("tear_off_btn"); +	mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); + +	mChatHistory = getChild<LLChatHistory>("chat_history"); + +	mInputEditor = getChild<LLChatEntry>("chat_editor"); +	mInputEditor->setTextExpandedCallback(boost::bind(&LLIMConversation::reshapeChatHistory, this)); +	mInputEditor->setCommitOnFocusLost( FALSE ); +	mInputEditor->setPassDelete(TRUE); +	mInputEditor->setFont(LLViewerChat::getChatFont()); + +	mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; + +	setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); + +	buildParticipantList(); + +	updateHeaderAndToolbar(); + +	mSaveRect = isTornOff(); +	initRectControl(); + +	if (isChatMultiTab()) +	{ +		if (mIsNearbyChat) +		{ +			setCanClose(FALSE); +		} +		result = LLFloater::postBuild(); +	} +	else +	{ +		result = LLDockableFloater::postBuild(); +	} + +	return result; +} + +void LLIMConversation::draw() +{ +	LLTransientDockableFloater::draw(); + +	if (mRefreshTimer->hasExpired()) +	{ +		if (mParticipantList) +		{ +			mParticipantList->update(); +		} + +		refresh(); +		updateHeaderAndToolbar(); + +		// Restart the refresh timer +		mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); +	} +} + +void LLIMConversation::buildParticipantList() +{ +	if (mIsNearbyChat) +	{ +		LLLocalSpeakerMgr* speaker_manager = LLLocalSpeakerMgr::getInstance(); +		mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); +	} +	else +	{ +		LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); +		// for group and ad-hoc chat we need to include agent into list +		if(!mIsP2PChat && mSessionID.notNull() && speaker_manager) +		{ +			delete mParticipantList; // remove the old list and create a new one if the session id has changed +			mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); +		} +	} +	updateHeaderAndToolbar(); +} + +void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) +{ +	// TODO: Check this code when sort order menu will be added. (EM) +	if (!mParticipantList) +	{ +		return; +	} + +	std::string chosen_item = userdata.asString(); + +	if (chosen_item == "sort_name") +	{ +		mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); +	} + +} + +void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) +{ +	std::string item = userdata.asString(); + +	if (item == "compact_view" || item == "expanded_view") +	{ +		gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view"); +	} +	else +	{ +		bool prev_value = gSavedSettings.getBOOL(item); +		gSavedSettings.setBOOL(item, !prev_value); +	} + +	LLIMConversation::processChatHistoryStyleUpdate(); +} + + +bool LLIMConversation::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) +{ +	std::string item = userdata.asString(); +	bool is_plain_text_mode = gSavedSettings.getBOOL("PlainTextChatHistory"); + +	return is_plain_text_mode? item == "compact_view" : item == "expanded_view"; +} + + +bool LLIMConversation::onIMShowModesMenuItemCheck(const LLSD& userdata) +{ +	return gSavedSettings.getBOOL(userdata.asString()); +} + +// enable/disable states for the "show time" and "show names" items of the show-modes menu +bool LLIMConversation::onIMShowModesMenuItemEnable(const LLSD& userdata) +{ +	std::string item = userdata.asString(); +	bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); +	bool is_not_names = (item != "IMShowNamesForP2PConv"); +	return (plain_text && (is_not_names || mIsP2PChat)); +} + +void LLIMConversation::hideOrShowTitle() +{ +	const LLFloater::Params& default_params = LLFloater::getDefaultParams(); +	S32 floater_header_size = default_params.header_height; +	LLView* floater_contents = getChild<LLView>("contents_view"); + +	LLRect floater_rect = getLocalRect(); +	S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); +	LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); +	LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); +	mDragHandle->setShape(handle_rect); +	mDragHandle->setVisible(isTornOff()); +	floater_contents->setShape(contents_rect); +} + +void LLIMConversation::hideAllStandardButtons() +{ +	for (S32 i = 0; i < BUTTON_COUNT; i++) +	{ +		if (mButtons[i]) +		{ +			// Hide the standard header buttons in a docked IM floater. +			mButtons[i]->setVisible(false); +		} +	} +} + +void LLIMConversation::updateHeaderAndToolbar() +{ +	bool is_torn_off = !getHost(); +	if (!is_torn_off) +	{ +		hideAllStandardButtons(); +	} + +	hideOrShowTitle(); + +	// Participant list should be visible only in torn off floaters. +	bool is_participant_list_visible = +			is_torn_off +			&& gSavedSettings.getBOOL("IMShowControlPanel") +			&& !mIsP2PChat; + +	mParticipantListPanel->setVisible(is_participant_list_visible); + +	// Display collapse image (<<) if the floater is hosted +	// or if it is torn off but has an open control panel. +	bool is_expanded = !is_torn_off || is_participant_list_visible; +	mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + +	// toggle floater's drag handle and title visibility +	if (mDragHandle) +	{ +		mDragHandle->setTitleVisible(is_torn_off); +	} + +	// The button (>>) should be disabled for torn off P2P conversations. +	mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); + +	mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); + +	mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); + +	enableDisableCallBtn(); + +	showTranslationCheckbox(); +} + +void LLIMConversation::reshapeChatHistory() +{ +	LLRect chat_rect  = mChatHistory->getRect(); +	LLRect input_rect = mInputEditor->getRect(); + +	int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad); + +	chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height); +	mChatHistory->setShape(chat_rect); +} + +void LLIMConversation::showTranslationCheckbox(BOOL show) +{ +	getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE); +} + +// static +void LLIMConversation::processChatHistoryStyleUpdate() +{ +	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); +	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); +			iter != inst_list.end(); ++iter) +	{ +		LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); +		if (floater) +		{ +			floater->reloadMessages(); +		} +	} + +	LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); +	if (nearby_chat) +	{ +		nearby_chat->reloadMessages(); +	} +} + +void LLIMConversation::updateCallBtnState(bool callIsActive) +{ +	getChild<LLButton>("voice_call_btn")->setImageOverlay( +			callIsActive? getString("call_btn_stop") : getString("call_btn_start")); +    enableDisableCallBtn(); + +} + +void LLIMConversation::onSlide(LLIMConversation* self) +{ +	LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(self->getHost()); +	if (host_floater) +	{ +		// Hide the messages pane if a floater is hosted in the Conversations +		host_floater->collapseMessagesPane(true); +	} +	else ///< floater is torn off +	{ +		if (!self->mIsP2PChat) +		{ +			bool expand = !self->mParticipantListPanel->getVisible(); + +			// Expand/collapse the IM control panel +			self->mParticipantListPanel->setVisible(expand); + +			gSavedSettings.setBOOL("IMShowControlPanel", expand); + +			self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon")); +		} +	} +} + +/*virtual*/ +void LLIMConversation::onOpen(const LLSD& key) +{ +	LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); +    bool is_hosted = !!host_floater; +	if (is_hosted) +	{ +		// Show the messages pane when opening a floater hosted in the Conversations +		host_floater->collapseMessagesPane(false); +	} + +	setTornOff(!is_hosted); +	updateHeaderAndToolbar(); +} + +// virtual +void LLIMConversation::onClose(bool app_quitting) +{ +	// Always suppress the IM from the conversations list on close if present for any reason +	if (LLIMConversation::isChatMultiTab()) +	{ +		LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); +		if (im_box) +		{ +            im_box->removeConversationListItem(mKey); +        } +    } +} + +void LLIMConversation::onTearOffClicked() +{ +    setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); +    mSaveRect = isTornOff(); +    initRectControl(); +	LLFloater::onClickTearOff(this); +	updateHeaderAndToolbar(); +} + +// static +bool LLIMConversation::isChatMultiTab() +{ +	// Restart is required in order to change chat window type. +	return true; +} diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h new file mode 100644 index 0000000000..f21be94ee2 --- /dev/null +++ b/indra/newview/llimconversation.h @@ -0,0 +1,132 @@ +/** + * @file llimconversation.h + * @brief LLIMConversation class implements the common behavior of LNearbyChatBar + * @brief and LLIMFloater for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_IMCONVERSATION_H +#define LL_IMCONVERSATION_H + +#include "lllayoutstack.h" +#include "llparticipantlist.h" +#include "lltransientdockablefloater.h" +#include "llviewercontrol.h" +#include "lleventtimer.h" + +class LLPanelChatControlPanel; +class LLChatEntry; +class LLChatHistory; + +class LLIMConversation +	: public LLTransientDockableFloater +{ + +public: +	LOG_CLASS(LLIMConversation); + +	LLIMConversation(const LLUUID& session_id); +	~LLIMConversation(); + +	// reload all message with new settings of visual modes +	static void processChatHistoryStyleUpdate(); + +	/** +	 * Returns true if chat is displayed in multi tabbed floater +	 *         false if chat is displayed in multiple windows +	 */ +	static bool isChatMultiTab(); + +    static LLIMConversation* findConversation(const LLUUID& uuid); +    static LLIMConversation* getConversation(const LLUUID& uuid); + +	// show/hide the translation check box +	void showTranslationCheckbox(const BOOL visible = FALSE); + +	// LLFloater overrides +	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ void onClose(bool app_quitting); +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void draw(); + +protected: + +	// callback for click on any items of the visual states menu +	void onIMSessionMenuItemClicked(const LLSD& userdata); + +	// callback for check/uncheck of the expanded/collapse mode's switcher +	bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); + +	// +	bool onIMShowModesMenuItemCheck(const LLSD& userdata); +	bool onIMShowModesMenuItemEnable(const LLSD& userdata); +	static void onSlide(LLIMConversation *self); +	virtual void onTearOffClicked(); + +	// refresh a visual state of the Call button +	void updateCallBtnState(bool callIsActive); + +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn() = 0; + +	void buildParticipantList(); +	void onSortMenuItemClicked(const LLSD& userdata); + +	void hideOrShowTitle(); // toggle the floater's drag handle +	void hideAllStandardButtons(); + +	/// Update floater header and toolbar buttons when hosted/torn off state is toggled. +	void updateHeaderAndToolbar(); + +	bool mIsNearbyChat; +	bool mIsP2PChat; + +	LLLayoutPanel* mParticipantListPanel; +	LLParticipantList* mParticipantList; +	LLUUID mSessionID; + +	LLChatHistory* mChatHistory; +	LLChatEntry* mInputEditor; +	int mInputEditorTopPad; // padding between input field and chat history + +	LLButton* mExpandCollapseBtn; +	LLButton* mTearOffBtn; +	LLButton* mCloseBtn; + +private: +	/// Refreshes the floater at a constant rate. +	virtual void refresh() = 0; + + +	/** +	 * Adjusts chat history height to fit vertically with input chat field +	 * and avoid overlapping, since input chat field can be vertically expanded. +	 * Implementation: chat history bottom "follows" top+top_pad of input chat field +	 */ +	void reshapeChatHistory(); + +	LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. +}; + + +#endif // LL_IMCONVERSATION_H diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 63eedcdfea..1c6445610f 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -28,44 +28,48 @@  #include "llimfloater.h" +#include "lldraghandle.h"  #include "llnotificationsutil.h"  #include "llagent.h"  #include "llappviewer.h" +#include "llavataractions.h"  #include "llavatarnamecache.h"  #include "llbutton.h"  #include "llchannelmanager.h"  #include "llchiclet.h"  #include "llchicletbar.h"  #include "llfloaterreg.h" +#include "llfloateravatarpicker.h"  #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container  #include "llinventoryfunctions.h" -#include "lllayoutstack.h" -#include "lllineeditor.h" +//#include "lllayoutstack.h" +#include "llchatentry.h"  #include "lllogchat.h" -#include "llpanelimcontrolpanel.h"  #include "llscreenchannel.h"  #include "llsyswellwindow.h"  #include "lltrans.h"  #include "llchathistory.h"  #include "llnotifications.h"  #include "llviewerwindow.h" -#include "llvoicechannel.h"  #include "lltransientfloatermgr.h"  #include "llinventorymodel.h"  #include "llrootview.h"  #include "llspeakers.h"  #include "llviewerchat.h" +#include "llnotificationmanager.h"  #include "llautoreplace.h" +/// Helper function to resolve resident names from given uuids +/// and form a string of names separated by "words_separator". +static void build_names_string(const uuid_vec_t& uuids, std::string& names_string); + +floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal; +  LLIMFloater::LLIMFloater(const LLUUID& session_id) -  : LLTransientDockableFloater(NULL, true, session_id), -	mControlPanel(NULL), -	mSessionID(session_id), +  : LLIMConversation(session_id),  	mLastMessageIndex(-1),  	mDialog(IM_NOTHING_SPECIAL), -	mChatHistory(NULL), -	mInputEditor(NULL),  	mSavedTitle(),  	mTypingStart(),  	mShouldSendTypingState(false), @@ -74,38 +78,13 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  	mTypingTimer(),  	mTypingTimeoutTimer(),  	mPositioned(false), -	mSessionInitialized(false) +	mSessionInitialized(false), +	mStartConferenceInSameFloater(false)  { -	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID); -	if (im_session) -	{ -		mSessionInitialized = im_session->mSessionInitialized; +	mIsNearbyChat = false; + +	initIMSession(session_id); -		mDialog = im_session->mType; -		switch(mDialog){ -		case IM_NOTHING_SPECIAL: -		case IM_SESSION_P2P_INVITE: -			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); -			break; -		case IM_SESSION_CONFERENCE_START: -			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); -			break; -		case IM_SESSION_GROUP_START: -			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); -			break; -		case IM_SESSION_INVITE:		 -			if (gAgent.isInGroup(mSessionID)) -			{ -				mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); -			} -			else -			{ -				mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); -			} -			break; -		default: break; -		} -	}  	setOverlapsScreenChannel(true);  	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); @@ -122,41 +101,68 @@ void LLIMFloater::onFocusLost()  void LLIMFloater::onFocusReceived()  { -	LLIMModel::getInstance()->setActiveSessionID(mSessionID); -  	LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true);  	if (getVisible())  	{ +		// suppress corresponding toast only if this floater is visible and have focus +		LLIMModel::getInstance()->setActiveSessionID(mSessionID);  		LLIMModel::instance().sendNoUnreadMessages(mSessionID);  	}  }  // virtual -void LLIMFloater::onClose(bool app_quitting) +void LLIMFloater::refresh()  { +	if (mMeTyping) +{ +		// Time out if user hasn't typed for a while. +		if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS) +		{  	setTyping(false); +		} +	} +} -	// The source of much argument and design thrashing -	// Should the window hide or the session close when the X is clicked? -	// -	// Last change: -	// EXT-3516 X Button should end IM session, _ button should hide -	gIMMgr->leaveSession(mSessionID); +// virtual +void LLIMFloater::onClickCloseBtn() +{ +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); + +	if (session == NULL) +	{ +		llwarns << "Empty session with id: " << (mSessionID.asString()) << llendl; +		return; +	} + +	bool is_call_with_chat = session->isGroupSessionType() +			|| session->isAdHocSessionType() || session->isP2PSessionType(); + +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + +	if (is_call_with_chat && voice_channel != NULL +			&& voice_channel->isActive()) +	{ +		LLSD payload; +		payload["session_id"] = mSessionID; +		LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); +		return; +	} + +	LLIMConversation::onClickCloseBtn();  }  /* static */ -void LLIMFloater::newIMCallback(const LLSD& data){ -	 +void LLIMFloater::newIMCallback(const LLSD& data) +{  	if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull())  	{  		LLUUID session_id = data["session_id"].asUUID();  		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -		if (floater == NULL) return;          // update if visible, otherwise will be updated when opened -		if (floater->getVisible()) +		if (floater && floater->getVisible())  		{  			floater->updateMessages();  		} @@ -183,113 +189,112 @@ void LLIMFloater::onVisibilityChange(const LLSD& new_visibility)  void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )  {  	LLIMFloater* self = (LLIMFloater*) userdata; -	self->sendMsg(); +	self->sendMsgFromInputEditor();  	self->setTyping(false);  } -void LLIMFloater::sendMsg() +void LLIMFloater::sendMsgFromInputEditor()  { -	if (!gAgent.isGodlike()  -		&& (mDialog == IM_NOTHING_SPECIAL) -		&& mOtherParticipantUUID.isNull()) +	if (gAgent.isGodlike() +		|| (mDialog != IM_NOTHING_SPECIAL) +		|| !mOtherParticipantUUID.isNull())  	{ -		llinfos << "Cannot send IM to everyone unless you're a god." << llendl; -		return; -	} - -	if (mInputEditor) -	{ -		LLWString text = mInputEditor->getConvertedText(); -		if(!text.empty()) +		if (mInputEditor)  		{ -			// Truncate and convert to UTF8 for transport -			std::string utf8_text = wstring_to_utf8str(text); -			utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); -			 -			if (mSessionInitialized) -			{ -				LLIMModel::sendMessage(utf8_text, mSessionID, -					mOtherParticipantUUID,mDialog); -			} -			else +			LLWString text = mInputEditor->getWText(); +			LLWStringUtil::trim(text); +			LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. +			if(!text.empty())  			{ -				//queue up the message to send once the session is initialized -				mQueuedMsgsForInit.append(utf8_text); -			} +				// Truncate and convert to UTF8 for transport +				std::string utf8_text = wstring_to_utf8str(text); -			mInputEditor->setText(LLStringUtil::null); +				sendMsg(utf8_text); -			updateMessages(); +				mInputEditor->setText(LLStringUtil::null); +			}  		}  	} +	else +	{ +		llinfos << "Cannot send IM to everyone unless you're a god." << llendl; +	}  } +void LLIMFloater::sendMsg(const std::string& msg) +{ +	const std::string utf8_text = utf8str_truncate(msg, MAX_MSG_BUF_SIZE - 1); +	if (mSessionInitialized) +	{ +		LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); +	} +	else +	{ +		//queue up the message to send once the session is initialized +		mQueuedMsgsForInit.append(utf8_text); +	} -LLIMFloater::~LLIMFloater() -{ -	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); +	updateMessages();  } -//virtual -BOOL LLIMFloater::postBuild() +LLIMFloater::~LLIMFloater()  { -	const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID); -	if (other_party_id.notNull()) +	mParticipantsListRefreshConnection.disconnect(); +	mVoiceChannelStateChangeConnection.disconnect(); +	if(LLVoiceClient::instanceExists())  	{ -		mOtherParticipantUUID = other_party_id; +		LLVoiceClient::getInstance()->removeObserver(this);  	} -	mControlPanel->setSessionId(mSessionID); -	mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); +	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); +} -	LLButton* slide_left = getChild<LLButton>("slide_left_btn"); -	slide_left->setVisible(mControlPanel->getParent()->getVisible()); -	slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); -	LLButton* slide_right = getChild<LLButton>("slide_right_btn"); -	slide_right->setVisible(!mControlPanel->getParent()->getVisible()); -	slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); +void LLIMFloater::initIMSession(const LLUUID& session_id) +{ +	// Change the floater key to bind it to a new session. +	setKey(session_id); -	mInputEditor = getChild<LLLineEditor>("chat_editor"); -	mInputEditor->setMaxTextLength(1023); -	// enable line history support for instant message bar -	mInputEditor->setEnableLineHistory(TRUE); -	// *TODO Establish LineEditor with autoreplace callback -	mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); +	mSessionID = session_id; +	mSession = LLIMModel::getInstance()->findIMSession(mSessionID); -	LLFontGL* font = LLViewerChat::getChatFont(); -	mInputEditor->setFont(font);	 -	 -	mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); -	mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); -	mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); -	mInputEditor->setCommitOnFocusLost( FALSE ); -	mInputEditor->setRevertOnEsc( FALSE ); -	mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); -	mInputEditor->setPassDelete( TRUE ); +	if (mSession) +	{ +		mIsP2PChat = mSession->isP2PSessionType(); +		mSessionInitialized = mSession->mSessionInitialized; -	childSetCommitCallback("chat_editor", onSendMsg, this); -	 -	mChatHistory = getChild<LLChatHistory>("chat_history"); +		mDialog = mSession->mType; +	} +} -	setDocked(true); +void LLIMFloater::initIMFloater() +{ +	const LLUUID& other_party_id = +			LLIMModel::getInstance()->getOtherParticipantID(mSessionID); +	if (other_party_id.notNull()) +	{ +		mOtherParticipantUUID = other_party_id; +	} + +	boundVoiceChannel();  	mTypingStart = LLTrans::getString("IM_typing_start_string"); +	// Show control panel in torn off floaters only. +	mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel")); +  	// Disable input editor if session cannot accept text -	LLIMModel::LLIMSession* im_session = -		LLIMModel::instance().findIMSession(mSessionID); -	if( im_session && !im_session->mTextIMPossible ) +	if ( mSession && !mSession->mTextIMPossible )  	{  		mInputEditor->setEnabled(FALSE);  		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));  	} -	if ( im_session && im_session->isP2PSessionType()) +	if (mIsP2PChat)  	{  		// look up display name for window title -		LLAvatarNameCache::get(im_session->mOtherParticipantID, +		LLAvatarNameCache::get(mSession->mOtherParticipantID,  							   boost::bind(&LLIMFloater::onAvatarNameCache,  										   this, _1, _2));  	} @@ -297,167 +302,433 @@ BOOL LLIMFloater::postBuild()  	{  		std::string session_name(LLIMModel::instance().getName(mSessionID));  		updateSessionName(session_name, session_name); + +		// For ad hoc conferences we should update the title with participants names. +		if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) +						|| mDialog == IM_SESSION_CONFERENCE_START) +		{ +			if (mParticipantsListRefreshConnection.connected()) +			{ +				mParticipantsListRefreshConnection.disconnect(); +			} + +			LLAvatarList* avatar_list = getChild<LLAvatarList>("speakers_list"); +			mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback( +					boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1)); +		}  	} +} + +//virtual +BOOL LLIMFloater::postBuild() +{ +	BOOL result = LLIMConversation::postBuild(); + +	mInputEditor->setMaxTextLength(1023); +	// enable line history support for instant message bar +	// XXX stinson TODO : resolve merge by adding autoreplace to text editors +#if 0 +	// *TODO Establish LineEditor with autoreplace callback +	mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); +#endif +	 +	mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); +	mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); +	mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) ); +	mInputEditor->setCommitCallback(boost::bind(onSendMsg, _1, this)); + +	setDocked(true); + +	LLButton* add_btn = getChild<LLButton>("add_btn"); + +	// Allow to add chat participants depending on the session type +	add_btn->setEnabled(isInviteAllowed()); +	add_btn->setClickedCallback(boost::bind(&LLIMFloater::onAddButtonClicked, this)); + +	childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this)); + +	LLVoiceClient::getInstance()->addObserver(this);  	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"  	//see LLFloaterIMPanel for how it is done (IB) -	if(isChatMultiTab()) +	initIMFloater(); + +	return result; +} + +void LLIMFloater::onAddButtonClicked() +{ +	LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE); +	if (!picker)  	{ -		return LLFloater::postBuild(); +		return;  	} -	else + +	// Need to disable 'ok' button when selected users are already in conversation. +	picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); +	LLFloater* root_floater = gFloaterView->getParentFloater(this); +	if (root_floater)  	{ -		return LLDockableFloater::postBuild(); +		root_floater->addDependentFloater(picker);  	}  } -void LLIMFloater::updateSessionName(const std::string& ui_title, -									const std::string& ui_label) +bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids)  { -	mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label); -	setTitle(ui_title);	 +	if (!mSession +		|| mDialog == IM_SESSION_GROUP_START +		|| mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) +	{ +		return false; +	} + +	if (mIsP2PChat) +	{ +		// For a P2P session just check if we are not adding the other participant. + +		for (uuid_vec_t::const_iterator id = uuids.begin(); +				id != uuids.end(); ++id) +		{ +			if (*id == mOtherParticipantUUID) +			{ +				return false; +			} +		} +	} +	else +	{ +		// For a conference session we need to check against the list from LLSpeakerMgr, +		// because this list may change when participants join or leave the session. + +		LLSpeakerMgr::speaker_list_t speaker_list; +		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); +		if (speaker_mgr) +		{ +			speaker_mgr->getSpeakerList(&speaker_list, true); +		} +	 +		for (uuid_vec_t::const_iterator id = uuids.begin(); +				id != uuids.end(); ++id) +		{ +			for (LLSpeakerMgr::speaker_list_t::const_iterator it = speaker_list.begin(); +					it != speaker_list.end(); ++it) +			{ +				const LLPointer<LLSpeaker>& speaker = *it; +				if (*id == speaker->mID) +				{ +					return false; +				} +			} +		} +	} + +	return true;  } -void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, -									const LLAvatarName& av_name) +void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids)  { -	// Use display name only for labels, as the extended name will be in the -	// floater title -	std::string ui_title = av_name.getCompleteName(); -	updateSessionName(ui_title, av_name.mDisplayName); -	mTypingStart.setArg("[NAME]", ui_title); +	if (mIsP2PChat) +	{ +		LLSD payload; +		LLSD args; + +		LLNotificationsUtil::add("ConfirmAddingChatParticipants", args, payload, +				boost::bind(&LLIMFloater::addP2PSessionParticipants, this, _1, _2, uuids)); +	} +	else +	{ +		// remember whom we have invited, to notify others later, when the invited ones actually join +		mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); +		 +		inviteToSession(uuids); +	}  } -// virtual -void LLIMFloater::draw() +void LLIMFloater::addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids)  { -	if ( mMeTyping ) +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	if (option != 0)  	{ -		// Time out if user hasn't typed for a while. -		if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS ) -		{ -			setTyping(false); -		} +		return;  	} -	LLTransientDockableFloater::draw(); +	mStartConferenceInSameFloater = true; + +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + +	// first check whether this is a voice session +	bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); + +	uuid_vec_t temp_ids; + +	// Add the initial participant of a P2P session +	temp_ids.push_back(mOtherParticipantUUID); +	temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end()); + +	// then we can close the current session +	onClose(false); + +	// we start a new session so reset the initialization flag +	mSessionInitialized = false; + +	// remember whom we have invited, to notify others later, when the invited ones actually join +	mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); + +	// Start a new ad hoc voice call if we invite new participants to a P2P call, +	// or start a text chat otherwise. +	if (is_voice_call) +	{ +		LLAvatarActions::startAdhocCall(temp_ids, mSessionID); +	} +	else +	{ +		LLAvatarActions::startConference(temp_ids, mSessionID); +	}  } +void LLIMFloater::sendParticipantsAddedNotification(const uuid_vec_t& uuids) +{ +	std::string names_string; +	build_names_string(uuids, names_string); +	LLStringUtil::format_map_t args; +	args["[NAME]"] = names_string; -// static -void* LLIMFloater::createPanelIMControl(void* userdata) +	sendMsg(getString(uuids.size() > 1 ? "multiple_participants_added" : "participant_added", args)); +} + +void LLIMFloater::boundVoiceChannel()  { -	LLIMFloater *self = (LLIMFloater*)userdata; -	self->mControlPanel = new LLPanelIMControlPanel(); -	self->mControlPanel->setXMLFilename("panel_im_control_panel.xml"); -	return self->mControlPanel; +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); +	if(voice_channel) +	{ +		mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback( +				boost::bind(&LLIMFloater::onVoiceChannelStateChanged, this, _1, _2)); + +		//call (either p2p, group or ad-hoc) can be already in started state +		bool callIsActive = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; +		updateCallBtnState(callIsActive); +	}  } +void LLIMFloater::enableDisableCallBtn() +{ +	bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() +			&& LLVoiceClient::getInstance()->isVoiceWorking(); -// static -void* LLIMFloater::createPanelGroupControl(void* userdata) +	if (mSession) +	{ +		bool session_initialized = mSession->mSessionInitialized; +		bool callback_enabled = mSession->mCallBackEnabled; + +		BOOL enable_connect = +				session_initialized && voice_enabled && callback_enabled; +		getChildView("voice_call_btn")->setEnabled(enable_connect); +	} +	else +	{ +		getChildView("voice_call_btn")->setEnabled(false); +	} +} + + +void LLIMFloater::onCallButtonClicked()  { -	LLIMFloater *self = (LLIMFloater*)userdata; -	self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID); -	self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); -	return self->mControlPanel; +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); +	if (voice_channel) +	{ +		bool is_call_active = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; +	    if (is_call_active) +	    { +		    gIMMgr->endCall(mSessionID); +	    } +	    else +	    { +		    gIMMgr->startCall(mSessionID); +	    } +	}  } -// static -void* LLIMFloater::createPanelAdHocControl(void* userdata) +void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal)  { -	LLIMFloater *self = (LLIMFloater*)userdata; -	self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID); -	self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml"); -	return self->mControlPanel; +	if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL) +	{ +		enableDisableCallBtn(); +	}  } -void LLIMFloater::onSlide() +void LLIMFloater::onVoiceChannelStateChanged( +		const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)  { -	mControlPanel->getParent()->setVisible(!mControlPanel->getParent()->getVisible()); +	bool callIsActive = new_state >= LLVoiceChannel::STATE_CALL_STARTED; +	updateCallBtnState(callIsActive); +} -	gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getParent()->getVisible()); +void LLIMFloater::updateSessionName(const std::string& ui_title, +									const std::string& ui_label) +{ +	mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label); +	setTitle(ui_title);	 +} -	getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getParent()->getVisible()); -	getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getParent()->getVisible()); +void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, +									const LLAvatarName& av_name) +{ +	// Use display name only for labels, as the extended name will be in the +	// floater title +	std::string ui_title = av_name.getCompleteName(); +	updateSessionName(ui_title, av_name.mDisplayName); +	mTypingStart.setArg("[NAME]", ui_title);  } -//static -LLIMFloater* LLIMFloater::show(const LLUUID& session_id) +void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl)  { -	closeHiddenIMToasts(); +	LLAvatarList* avatar_list = dynamic_cast<LLAvatarList*>(ctrl); +	if (!avatar_list) +	{ +		return; +	} -	if (!gIMMgr->hasSession(session_id)) return NULL; +	bool all_names_resolved = true; +	std::vector<LLSD> participants_uuids; +	uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string -	if(!isChatMultiTab()) +	avatar_list->getValues(participants_uuids); + +	// Check whether we have all participants names in LLAvatarNameCache +    for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it)  	{ -		//hide all -		LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); -		for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); -			 iter != inst_list.end(); ++iter) -		{ -			LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); -			if (floater && floater->isDocked()) -			{ -				floater->setVisible(false); -			} -		} +		const LLUUID& id = it->asUUID(); +		temp_uuids.push_back(id); +		LLAvatarName av_name; +        if (!LLAvatarNameCache::get(id, &av_name)) +        { +			all_names_resolved = false; + +			// If a name is not found in cache, request it and continue the process recursively +			// until all ids are resolved into names. +			LLAvatarNameCache::get(id, +					boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); +			break; +        } +	} + +	if (all_names_resolved) +	{ +		std::string ui_title; +		build_names_string(temp_uuids, ui_title); +		updateSessionName(ui_title, ui_title);  	} +    } +//static +LLIMFloater* LLIMFloater::addToIMContainer(const LLUUID& session_id) +{ +	if (!gIMMgr->hasSession(session_id)) +		return NULL; + +	// Test the existence of the floater before we try to create it  	bool exist = findInstance(session_id); +	// Get the floater: this will create the instance if it didn't exist  	LLIMFloater* floater = getInstance(session_id); -	if (!floater) return NULL; - -	if(isChatMultiTab()) +	if (floater)  	{ +  		LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); -		// do not add existed floaters to avoid adding torn off instances +		// Do not add again existing floaters  		if (!exist)  		{  			//		LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;  			// TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists  			LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; -			  			if (floater_container)  			{  				floater_container->addFloater(floater, TRUE, i_pt);  			}  		} -		floater->openFloater(floater->getKey()); +		if (floater_container && floater_container->getVisible()) +		{ +			floater->openFloater(floater->getKey()); +			floater->setVisible(TRUE); +		} +		else +		{ +			floater->setVisible(FALSE); +		}  	} -	else -	{ -		// Docking may move chat window, hide it before moving, or user will see how window "jumps" -		floater->setVisible(false); +	return floater; +} -		if (floater->getDockControl() == NULL) -		{ -			LLChiclet* chiclet = -					LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLChiclet>( -							session_id); -			if (chiclet == NULL) -			{ -				llerror("Dock chiclet for LLIMFloater doesn't exists", 0); -			} -			else -			{ -				LLChicletBar::getInstance()->getChicletPanel()->scrollToChiclet(chiclet); -			} +//static +LLIMFloater* LLIMFloater::show(const LLUUID& session_id) +{ +	closeHiddenIMToasts(); -			floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), -					LLDockControl::BOTTOM)); -		} +	if (!gIMMgr->hasSession(session_id)) +		return NULL; + +	// Test the existence of the floater before we try to create it +	bool exist = findInstance(session_id); + +	// Get the floater: this will create the instance if it didn't exist +	LLIMFloater* floater = getInstance(session_id); +	if (!floater) +		return NULL; -		// window is positioned, now we can show it. +	LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); + +	// Do not add again existing floaters +	if (!exist) +	{ +		//		LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; +		// TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists +		LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; +		if (floater_container) +		{ +			floater_container->addFloater(floater, TRUE, i_pt); +		}  	} + +	floater->openFloater(floater->getKey()); +  	floater->setVisible(TRUE);  	return floater;  } +//static +LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) +{ +    LLIMFloater* conversation = +    		LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); + +	return conversation; +} + +LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) +{ +	LLIMFloater* conversation = +				LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); + +	return conversation; +} + +void LLIMFloater::onClose(bool app_quitting) +{ +	setTyping(false); + +	// The source of much argument and design thrashing +	// Should the window hide or the session close when the X is clicked? +	// +	// Last change: +	// EXT-3516 X Button should end IM session, _ button should hide +	gIMMgr->leaveSession(mSessionID); + +	// Clean up the conversation *after* the session has been ended +	LLIMConversation::onClose(app_quitting); +}  void LLIMFloater::setDocked(bool docked, bool pop_on_undock)  { @@ -484,6 +755,7 @@ void LLIMFloater::setVisible(BOOL visible)  	LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>  		(LLNotificationsUI::LLChannelManager::getInstance()->  											findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); +  	LLTransientDockableFloater::setVisible(visible);  	// update notification channel state @@ -516,13 +788,21 @@ void LLIMFloater::setVisible(BOOL visible)  			chiclet->setToggleState(false);  		}  	} + +	if (visible && isInVisibleChain()) +	{ +		sIMFloaterShowedSignal(mSessionID); +	}  }  BOOL LLIMFloater::getVisible()  { +	bool visible; +  	if(isChatMultiTab())  	{ -		LLIMFloaterContainer* im_container = LLIMFloaterContainer::getInstance(); +		LLIMFloaterContainer* im_container = +				LLIMFloaterContainer::getInstance();  		// Treat inactive floater as invisible.  		bool is_active = im_container->getActiveFloater() == this; @@ -530,16 +810,21 @@ BOOL LLIMFloater::getVisible()  		//torn off floater is always inactive  		if (!is_active && getHost() != im_container)  		{ -			return LLTransientDockableFloater::getVisible(); +			visible = LLTransientDockableFloater::getVisible();  		} - +		else +		{  		// getVisible() returns TRUE when Tabbed IM window is minimized. -		return is_active && !im_container->isMinimized() && im_container->getVisible(); +			visible = is_active && !im_container->isMinimized() +						&& im_container->getVisible(); +	}  	}  	else  	{ -		return LLTransientDockableFloater::getVisible(); +		visible = LLTransientDockableFloater::getVisible();  	} + +	return visible;  }  //static @@ -547,7 +832,8 @@ bool LLIMFloater::toggle(const LLUUID& session_id)  {  	if(!isChatMultiTab())  	{ -		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); +		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>( +				"impanel", session_id);  		if (floater && floater->getVisible() && floater->hasFocus())  		{  			// clicking on chiclet to close floater just hides it to maintain existing @@ -568,17 +854,6 @@ bool LLIMFloater::toggle(const LLUUID& session_id)  	return true;  } -//static -LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) -{ -	return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -} - -LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) -{ -	return LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); -} -  void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)  {  	mSessionInitialized = true; @@ -586,53 +861,59 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)  	//will be different only for an ad-hoc im session  	if (mSessionID != im_session_id)  	{ -		mSessionID = im_session_id; -		setKey(im_session_id); -		mControlPanel->setSessionId(im_session_id); -	} +		initIMSession(im_session_id); -	// updating "Call" button from group control panel here to enable it without placing into draw() (EXT-4796) -	if(gAgent.isInGroup(im_session_id)) -	{ -		mControlPanel->updateCallButton(); +		buildParticipantList();  	} + +	initIMFloater();  	//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) +	//need to send delayed messages collected while waiting for session initialization +	if (mQueuedMsgsForInit.size()) +	{ +		LLSD::array_iterator iter; +		for ( iter = mQueuedMsgsForInit.beginArray(); +					iter != mQueuedMsgsForInit.endArray(); ++iter) +		{ +			LLIMModel::sendMessage(iter->asString(), mSessionID, +				mOtherParticipantUUID, mDialog); +		} + +		mQueuedMsgsForInit.clear(); +	} +} + +void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args) +{ +	LLChat& tmp_chat = const_cast<LLChat&>(chat); -	//need to send delayed messaged collected while waiting for session initialization -	if (!mQueuedMsgsForInit.size()) return; -	LLSD::array_iterator iter; -	for ( iter = mQueuedMsgsForInit.beginArray(); -		iter != mQueuedMsgsForInit.endArray(); -		++iter) +	if (!chat.mMuted)  	{ -		LLIMModel::sendMessage(iter->asString(), mSessionID, -			mOtherParticipantUUID, mDialog); +		tmp_chat.mFromName = chat.mFromName; +		LLSD chat_args; +		if (args) chat_args = args; +		chat_args["use_plain_text_chat_history"] = +				gSavedSettings.getBOOL("PlainTextChatHistory"); +		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); +		chat_args["show_names_for_p2p_conv"] = !mIsP2PChat +				|| gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + +		mChatHistory->appendMessage(chat, chat_args);  	}  }  void LLIMFloater::updateMessages()  { -	bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory"); -  	std::list<LLSD> messages;  	// we shouldn't reset unread message counters if IM floater doesn't have focus -	if (hasFocus()) -	{ -		LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1); -	} -	else -	{ -		LLIMModel::instance().getMessagesSilently(mSessionID, messages, mLastMessageIndex+1); -	} +    LLIMModel::instance().getMessages( +    		mSessionID, messages, mLastMessageIndex + 1, hasFocus());  	if (messages.size())  	{ -		LLSD chat_args; -		chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; -  		std::ostringstream message;  		std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();  		std::list<LLSD>::const_reverse_iterator iter_end = messages.rend(); @@ -682,7 +963,7 @@ void LLIMFloater::updateMessages()  				chat.mText = message;  			} -			mChatHistory->appendMessage(chat, chat_args); +			appendMessage(chat);  			mLastMessageIndex = msg["index"].asInteger();  			// if it is a notification - next message is a notification history log, so skip it @@ -706,6 +987,7 @@ void LLIMFloater::reloadMessages()  	mChatHistory->clear();  	mLastMessageIndex = -1;  	updateMessages(); +	mInputEditor->setFont(LLViewerChat::getChatFont());  }  // static @@ -732,19 +1014,13 @@ void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userd  }  // static -void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) +void LLIMFloater::onInputEditorKeystroke(LLTextEditor* caller, void* userdata)  {  	LLIMFloater* self = (LLIMFloater*)userdata;  	std::string text = self->mInputEditor->getText(); -	if (!text.empty()) -	{ -		self->setTyping(true); -	} -	else -	{ +  		// Deleting all text counts as stopping typing. -		self->setTyping(false); -	} +	self->setTyping(!text.empty());  }  void LLIMFloater::setTyping(bool typing) @@ -769,27 +1045,24 @@ void LLIMFloater::setTyping(bool typing)  	// much network traffic. Only send in person-to-person IMs.  	if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL )  	{ -		if ( mMeTyping ) +		// Still typing, send 'start typing' notification or +		// send 'stop typing' notification immediately +		if (!mMeTyping || mTypingTimer.getElapsedTimeF32() > 1.f)  		{ -			if ( mTypingTimer.getElapsedTimeF32() > 1.f ) -			{ -				// Still typing, send 'start typing' notification -				LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE); -				mShouldSendTypingState = false; -			} +			LLIMModel::instance().sendTypingState(mSessionID, +					mOtherParticipantUUID, mMeTyping); +					mShouldSendTypingState = false;  		} -		else +	} + +	if (!mIsNearbyChat) +	{ +		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); +		if (speaker_mgr)  		{ -			// Send 'stop typing' notification immediately -			LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE); -			mShouldSendTypingState = false; +			speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);  		}  	} - -	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); -	if (speaker_mgr) -		speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); -  }  void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) @@ -808,55 +1081,66 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)  void LLIMFloater::processAgentListUpdates(const LLSD& body)  { -	if ( !body.isMap() ) return; +	uuid_vec_t joined_uuids; -	if ( body.has("agent_updates") && body["agent_updates"].isMap() ) +	if (body.isMap() && body.has("agent_updates") && body["agent_updates"].isMap())  	{ -		LLSD agent_data = body["agent_updates"].get(gAgentID.asString()); -		if (agent_data.isMap() && agent_data.has("info")) +		LLSD::map_const_iterator update_it; +		for(update_it = body["agent_updates"].beginMap(); +			update_it != body["agent_updates"].endMap(); +			++update_it)  		{ -			LLSD agent_info = agent_data["info"]; +			LLUUID agent_id(update_it->first); +			LLSD agent_data = update_it->second; -			if (agent_info.has("mutes")) +			if (agent_data.isMap())  			{ -				BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean();  -				mInputEditor->setEnabled(!moderator_muted_text); -				std::string label; -				if (moderator_muted_text) -					label = LLTrans::getString("IM_muted_text_label"); -				else -					label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID); -				mInputEditor->setLabel(label); +				// store the new participants in joined_uuids +				if (agent_data.has("transition") && agent_data["transition"].asString() == "ENTER") +				{ +					joined_uuids.push_back(agent_id); +				} -				if (moderator_muted_text) -					LLNotificationsUtil::add("TextChatIsMutedByModerator"); +				// process the moderator mutes +				if (agent_id == gAgentID && agent_data.has("info") && agent_data["info"].has("mutes")) +				{ +					BOOL moderator_muted_text = agent_data["info"]["mutes"]["text"].asBoolean(); +					mInputEditor->setEnabled(!moderator_muted_text); +					std::string label; +					if (moderator_muted_text) +						label = LLTrans::getString("IM_muted_text_label"); +					else +						label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID); +					mInputEditor->setLabel(label); + +					if (moderator_muted_text) +						LLNotificationsUtil::add("TextChatIsMutedByModerator"); +				}  			}  		}  	} -} -void LLIMFloater::updateChatHistoryStyle() -{ -	mChatHistory->clear(); -	mLastMessageIndex = -1; -	updateMessages(); -} +	// the vectors need to be sorted for computing the intersection and difference +	std::sort(mInvitedParticipants.begin(), mInvitedParticipants.end()); +    std::sort(joined_uuids.begin(), joined_uuids.end()); -void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue) -{ -	LLFontGL* font = LLViewerChat::getChatFont(); -	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); -	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); -		 iter != inst_list.end(); ++iter) +    uuid_vec_t intersection; // uuids of invited residents who have joined the conversation +	std::set_intersection(mInvitedParticipants.begin(), mInvitedParticipants.end(), +						  joined_uuids.begin(), joined_uuids.end(), +						  std::back_inserter(intersection)); + +	if (intersection.size() > 0)  	{ -		LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); -		if (floater) -		{ -			floater->updateChatHistoryStyle(); -			floater->mInputEditor->setFont(font); -		} +		sendParticipantsAddedNotification(intersection);  	} +	// Remove all joined participants from invited array. +	// The difference between the two vectors (the elements in mInvitedParticipants which are not in joined_uuids) +	// is placed at the beginning of mInvitedParticipants, then all other elements are erased. +	mInvitedParticipants.erase(std::set_difference(mInvitedParticipants.begin(), mInvitedParticipants.end(), +												   joined_uuids.begin(), joined_uuids.end(), +												   mInvitedParticipants.begin()), +							   mInvitedParticipants.end());  }  void LLIMFloater::processSessionUpdate(const LLSD& session_update) @@ -870,7 +1154,8 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update)  		if (voice_moderated)  		{ -			setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label")); +			setTitle(session_label + std::string(" ") +							+ LLTrans::getString("IM_moderated_chat_label"));  		}  		else  		{ @@ -883,98 +1168,56 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update)  	}  } -BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, -						   BOOL drop, EDragAndDropType cargo_type, -						   void *cargo_data, EAcceptance *accept, +// virtual +BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +									EDragAndDropType cargo_type, +									void* cargo_data, +									EAcceptance* accept,  						   std::string& tooltip_msg)  { - -	if (mDialog == IM_NOTHING_SPECIAL) +	if (cargo_type == DAD_PERSON)  	{ -		LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, -												 cargo_type, cargo_data, accept); -	} - -	// handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites -	else if (isInviteAllowed()) -	{ -		*accept = ACCEPT_NO; - -		if (cargo_type == DAD_CALLINGCARD) +		if (dropPerson(static_cast<LLUUID*>(cargo_data), drop))  		{ -			if (dropCallingCard((LLInventoryItem*)cargo_data, drop)) -			{ -				*accept = ACCEPT_YES_MULTI; -			} +			*accept = ACCEPT_YES_MULTI;  		} -		else if (cargo_type == DAD_CATEGORY) +		else  		{ -			if (dropCategory((LLInventoryCategory*)cargo_data, drop)) -			{ -				*accept = ACCEPT_YES_MULTI; -			} +			*accept = ACCEPT_NO;  		}  	} +	else if (mDialog == IM_NOTHING_SPECIAL) +	{ +		LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, +				cargo_type, cargo_data, accept); +	} +  	return TRUE;  } -BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) +bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop)  { -	BOOL rv = isInviteAllowed(); -	if(rv && item && item->getCreatorUUID().notNull()) -	{ -		if(drop) -		{ -			uuid_vec_t ids; -			ids.push_back(item->getCreatorUUID()); -			inviteToSession(ids); -		} -	} -	else +	bool res = person_id && person_id->notNull(); +	if(res)  	{ -		// set to false if creator uuid is null. -		rv = FALSE; -	} -	return rv; -} +		uuid_vec_t ids; +		ids.push_back(*person_id); -BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) -{ -	BOOL rv = isInviteAllowed(); -	if(rv && category) -	{ -		LLInventoryModel::cat_array_t cats; -		LLInventoryModel::item_array_t items; -		LLUniqueBuddyCollector buddies; -		gInventory.collectDescendentsIf(category->getUUID(), -										cats, -										items, -										LLInventoryModel::EXCLUDE_TRASH, -										buddies); -		S32 count = items.count(); -		if(count == 0) -		{ -			rv = FALSE; -		} -		else if(drop) +		res = canAddSelectedToChat(ids); +		if(res && drop)  		{ -			uuid_vec_t ids; -			ids.reserve(count); -			for(S32 i = 0; i < count; ++i) -			{ -				ids.push_back(items.get(i)->getCreatorUUID()); -			} -			inviteToSession(ids); +			addSessionParticipants(ids);  		}  	} -	return rv; + +	return res;  }  BOOL LLIMFloater::isInviteAllowed() const  { -  	return ( (IM_SESSION_CONFERENCE_START == mDialog) -			 || (IM_SESSION_INVITE == mDialog) ); +			 || (IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) +			 || mIsP2PChat);  }  class LLSessionInviteResponder : public LLHTTPClient::Responder @@ -998,45 +1241,39 @@ private:  BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids)  {  	LLViewerRegion* region = gAgent.getRegion(); -	if (!region) -	{ -		return FALSE; -	} +	bool is_region_exist = region != NULL; -	S32 count = ids.size(); - -	if( isInviteAllowed() && (count > 0) ) +	if (is_region_exist)  	{ -		llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; +		S32 count = ids.size(); -		std::string url = region->getCapability("ChatSessionRequest"); +		if( isInviteAllowed() && (count > 0) ) +		{ +			llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; -		LLSD data; +			std::string url = region->getCapability("ChatSessionRequest"); -		data["params"] = LLSD::emptyArray(); -		for (int i = 0; i < count; i++) +			LLSD data; +			data["params"] = LLSD::emptyArray(); +			for (int i = 0; i < count; i++) +			{ +				data["params"].append(ids[i]); +			} +			data["method"] = "invite"; +			data["session-id"] = mSessionID; +			LLHTTPClient::post(url,	data,new LLSessionInviteResponder(mSessionID)); +		} +		else  		{ -			data["params"].append(ids[i]); +			llinfos << "LLIMFloater::inviteToSession -" +					<< " no need to invite agents for " +					<< mDialog << llendl; +			// successful add, because everyone that needed to get added +			// was added.  		} - -		data["method"] = "invite"; -		data["session-id"] = mSessionID; -		LLHTTPClient::post( -			url, -			data, -			new LLSessionInviteResponder( -					mSessionID)); -	} -	else -	{ -		llinfos << "LLIMFloater::inviteToSession -" -				<< " no need to invite agents for " -				<< mDialog << llendl; -		// successful add, because everyone that needed to get added -		// was added.  	} -	return TRUE; +	return is_region_exist;  }  void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) @@ -1077,7 +1314,6 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)  				speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);  			}  		} -  	}  } @@ -1094,7 +1330,8 @@ void LLIMFloater::closeHiddenIMToasts()  		}  	}; -	LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getNotificationScreenChannel(); +	LLNotificationsUI::LLScreenChannel* channel = +			LLNotificationsUI::LLChannelManager::getNotificationScreenChannel();  	if (channel != NULL)  	{  		channel->closeHiddenToasts(IMToastMatcher()); @@ -1107,7 +1344,7 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD&  	const LLSD& payload = notification["payload"];  	LLUUID session_id = payload["session_id"]; -	LLFloater* im_floater = LLFloaterReg::findInstance("impanel", session_id); +	LLFloater* im_floater = findInstance(session_id);  	if (option == 0 && im_floater != NULL)  	{  		im_floater->closeFloater(); @@ -1117,79 +1354,71 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD&  }  // static -bool LLIMFloater::isChatMultiTab() -{ -	// Restart is required in order to change chat window type. -	static bool is_single_window = gSavedSettings.getS32("ChatWindow") == 1; -	return is_single_window; -} - -// static -void LLIMFloater::initIMFloater() -{ -	// This is called on viewer start up -	// init chat window type before user changed it in preferences -	isChatMultiTab(); -} - -//static  void LLIMFloater::sRemoveTypingIndicator(const LLSD& data)  {  	LLUUID session_id = data["session_id"]; -	if (session_id.isNull()) return; +	if (session_id.isNull()) +		return;  	LLUUID from_id = data["from_id"]; -	if (gAgentID == from_id || LLUUID::null == from_id) return; +	if (gAgentID == from_id || LLUUID::null == from_id) +		return;  	LLIMFloater* floater = LLIMFloater::findInstance(session_id); -	if (!floater) return; +	if (!floater) +		return; -	if (IM_NOTHING_SPECIAL != floater->mDialog) return; +	if (IM_NOTHING_SPECIAL != floater->mDialog) +		return;  	floater->removeTypingIndicator();  }  void LLIMFloater::onIMChicletCreated( const LLUUID& session_id )  { - -	if (isChatMultiTab()) +	LLIMFloater::addToHost(session_id); +} +void LLIMFloater::addToHost(const LLUUID& session_id)  	{ -		LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); -		if (!im_box) return; - -		if (LLIMFloater::findInstance(session_id)) return; - -		LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); - -		im_box->addFloater(new_tab, FALSE, LLTabContainer::END); +	if (LLIMConversation::isChatMultiTab()) +{ +		LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); +		if (!im_box) +	{ +			im_box = LLIMFloaterContainer::getInstance();  	} +		if (im_box && !LLIMFloater::findInstance(session_id)) +	{ +			LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); +			im_box->addFloater(new_tab, FALSE, LLTabContainer::END); +	} +	}  } -void	LLIMFloater::onClickCloseBtn() +boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb)  { +	return LLIMFloater::sIMFloaterShowedSignal.connect(cb); +} -	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( -				mSessionID); - -	if (session == NULL) +// static +void build_names_string(const uuid_vec_t& uuids, std::string& names_string) +{ +	std::vector<LLAvatarName> avatar_names; +	uuid_vec_t::const_iterator it = uuids.begin(); +	for (; it != uuids.end(); ++it)  	{ -		llwarns << "Empty session." << llendl; -		return; +		LLAvatarName av_name; +		if (LLAvatarNameCache::get(*it, &av_name)) +		{ +			avatar_names.push_back(av_name); +		}  	} -	bool is_call_with_chat = session->isGroupSessionType() -			|| session->isAdHocSessionType() || session->isP2PSessionType(); - -	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - -	if (is_call_with_chat && voice_channel != NULL && voice_channel->isActive()) +	// We should check whether the vector is not empty to pass the assertion +	// that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. +	if (!avatar_names.empty())  	{ -		LLSD payload; -		payload["session_id"] = mSessionID; -		LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); -		return; +		LLAvatarActions::buildResidentsString(avatar_names, names_string);  	} - -	LLFloater::onClickCloseBtn();  } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index f7cd35b5eb..24a8f17feb 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -27,59 +27,71 @@  #ifndef LL_IMFLOATER_H  #define LL_IMFLOATER_H +#include "llimview.h" +#include "llimconversation.h"  #include "llinstantmessage.h"  #include "lllogchat.h"  #include "lltooldraganddrop.h" -#include "lltransientdockablefloater.h" +#include "llvoicechannel.h" +#include "llvoiceclient.h"  class LLAvatarName; -class LLLineEditor; +class LLButton; +class LLChatEntry; +class LLTextEditor;  class LLPanelChatControlPanel;  class LLChatHistory;  class LLInventoryItem;  class LLInventoryCategory; +typedef boost::signals2::signal<void(const LLUUID& session_id)> floater_showed_signal_t; +  /**   * Individual IM window that appears at the bottom of the screen,   * optionally "docked" to the bottom tray.   */ -class LLIMFloater : public LLTransientDockableFloater +class LLIMFloater +    : public LLVoiceClientStatusObserver +    , public LLIMConversation  {  	LOG_CLASS(LLIMFloater);  public:  	LLIMFloater(const LLUUID& session_id);  	virtual ~LLIMFloater(); -	 + +	void initIMSession(const LLUUID& session_id); +	void initIMFloater(); +  	// LLView overrides  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setVisible(BOOL visible);  	/*virtual*/ BOOL getVisible();  	// Check typing timeout timer. -	/*virtual*/ void draw(); + +	static LLIMFloater* findInstance(const LLUUID& session_id); +	static LLIMFloater* getInstance(const LLUUID& session_id); +	static void addToHost(const LLUUID& session_id);  	// LLFloater overrides  	/*virtual*/ void onClose(bool app_quitting);  	/*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); -  	// Make IM conversion visible and update the message history  	static LLIMFloater* show(const LLUUID& session_id); +	static LLIMFloater* addToIMContainer(const LLUUID& session_id);  	// Toggle panel specified by session_id  	// Returns true iff panel became visible  	static bool toggle(const LLUUID& session_id); -	static LLIMFloater* findInstance(const LLUUID& session_id); - -	static LLIMFloater* getInstance(const LLUUID& session_id); -  	void sessionInitReplyReceived(const LLUUID& im_session_id);  	// get new messages from LLIMModel  	void updateMessages();  	void reloadMessages(); -	static void onSendMsg( LLUICtrl*, void*); -	void sendMsg(); +	static void onSendMsg(LLUICtrl*, void*); +	void sendMsgFromInputEditor(); +	void sendMsg(const std::string& msg);  	// callback for LLIMModel on new messages  	// route to specific floater if it is visible @@ -89,62 +101,78 @@ public:  	void setPositioned(bool b) { mPositioned = b; };  	void onVisibilityChange(const LLSD& new_visibility); + +	// Implements LLVoiceClientStatusObserver::onChange() to enable the call +	// button when voice is available +	void onChange(EStatusType status, const std::string &channelURI, +			bool proximal); + +	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } +	virtual void onVoiceChannelStateChanged( +			const LLVoiceChannel::EState& old_state, +			const LLVoiceChannel::EState& new_state); +  	void processIMTyping(const LLIMInfo* im_info, BOOL typing);  	void processAgentListUpdates(const LLSD& body);  	void processSessionUpdate(const LLSD& session_update); -	void updateChatHistoryStyle(); -	static void processChatHistoryStyleUpdate(const LLSD& newvalue); - -	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, -							   BOOL drop, EDragAndDropType cargo_type, -							   void *cargo_data, EAcceptance *accept, -							   std::string& tooltip_msg); - -	/** -	 * Returns true if chat is displayed in multi tabbed floater -	 *         false if chat is displayed in multiple windows -	 */ -	static bool isChatMultiTab(); +	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +									   EDragAndDropType cargo_type, +									   void* cargo_data, +									   EAcceptance* accept, +									   std::string& tooltip_msg); -	static void initIMFloater();  	//used as a callback on receiving new IM message  	static void sRemoveTypingIndicator(const LLSD& data); -  	static void onIMChicletCreated(const LLUUID& session_id); -	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } +	bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } -protected: -	/* virtual */ -	void	onClickCloseBtn(); +	static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); +	static floater_showed_signal_t sIMFloaterShowedSignal;  private: +  	// process focus events to set a currently active session  	/* virtual */ void onFocusLost();  	/* virtual */ void onFocusReceived(); +	/*virtual*/ void refresh(); + +	/*virtual*/ void onClickCloseBtn(); +  	// Update the window title, input field help text, etc.  	void updateSessionName(const std::string& ui_title, const std::string& ui_label); -	 +  	// For display name lookups for IM window titles  	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); -	 -	BOOL dropCallingCard(LLInventoryItem* item, BOOL drop); -	BOOL dropCategory(LLInventoryCategory* category, BOOL drop); + +	/// Updates the list of ad hoc conference participants +	/// in an IM floater title. +	void onParticipantsListChanged(LLUICtrl* ctrl); + +	bool dropPerson(LLUUID* person_id, bool drop);  	BOOL isInviteAllowed() const;  	BOOL inviteToSession(const uuid_vec_t& agent_ids); -	 -	static void		onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); -	static void		onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); -	static void		onInputEditorKeystroke(LLLineEditor* caller, void* userdata); -	void			setTyping(bool typing); -	void			onSlide(); -	static void*	createPanelIMControl(void* userdata); -	static void*	createPanelGroupControl(void* userdata); -	static void* 	createPanelAdHocControl(void* userdata); +	void appendMessage(const LLChat& chat, const LLSD &args = 0); +	static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); +	static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); +	static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); +	void setTyping(bool typing); +	void onAddButtonClicked(); +	void addSessionParticipants(const uuid_vec_t& uuids); +	void addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids); +	void sendParticipantsAddedNotification(const uuid_vec_t& uuids); +	bool canAddSelectedToChat(const uuid_vec_t& uuids); + +	void onCallButtonClicked(); + +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn(); + +	void boundVoiceChannel();  	// Add the "User is typing..." indicator.  	void addTypingIndicator(const LLIMInfo* im_info); @@ -156,14 +184,12 @@ private:  	static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); -	LLPanelChatControlPanel* mControlPanel; -	LLUUID mSessionID; + +	LLIMModel::LLIMSession* mSession;  	S32 mLastMessageIndex;  	EInstantMessage mDialog;  	LLUUID mOtherParticipantUUID; -	LLChatHistory* mChatHistory; -	LLLineEditor* mInputEditor;  	bool mPositioned;  	std::string mSavedTitle; @@ -176,7 +202,15 @@ private:  	bool mSessionInitialized;  	LLSD mQueuedMsgsForInit; -}; +	bool mStartConferenceInSameFloater; + +	uuid_vec_t mInvitedParticipants; + +	// connection to voice channel state change signal +	boost::signals2::connection mVoiceChannelStateChangeConnection; + +	boost::signals2::connection mParticipantsListRefreshConnection; +};  #endif  // LL_IMFLOATER_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 0f0ae896a2..35b9f404c3 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -27,20 +27,35 @@  #include "llviewerprecompiledheaders.h" +#include "llimfloater.h"  #include "llimfloatercontainer.h" +  #include "llfloaterreg.h" -#include "llimview.h" +#include "lllayoutstack.h" +#include "llnearbychat.h" + +#include "llagent.h" +#include "llavataractions.h"  #include "llavatariconctrl.h" +#include "llavatarnamecache.h"  #include "llgroupiconctrl.h" -#include "llagent.h" +#include "llfloateravatarpicker.h" +#include "llimview.h"  #include "lltransientfloatermgr.h" +#include "llviewercontrol.h" +#include "llconversationview.h"  //  // LLIMFloaterContainer  //  LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) -:	LLMultiFloater(seed) +:	LLMultiFloater(seed), +	mExpandCollapseBtn(NULL), +	mConversationsRoot(NULL)  { +	// Firstly add our self to IMSession observers, so we catch session events +    LLIMMgr::getInstance()->addSessionObserver(this); +  	mAutoResize = FALSE;  	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);  } @@ -49,6 +64,37 @@ LLIMFloaterContainer::~LLIMFloaterContainer()  {  	mNewMessageConnection.disconnect();  	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); + +	gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed()); +	gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed()); + +	if (!LLSingleton<LLIMMgr>::destroyed()) +	{ +		LLIMMgr::getInstance()->removeSessionObserver(this); +	} +} + +void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ +	LLIMFloater::addToIMContainer(session_id); +	addConversationListItem(session_id); +} + +void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) +{ +	LLIMFloater::addToIMContainer(session_id); +	addConversationListItem(session_id); +} + +void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) +{ +	removeConversationListItem(old_session_id); +	addConversationListItem(new_session_id); +} + +void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) +{ +	removeConversationListItem(session_id);  }  BOOL LLIMFloaterContainer::postBuild() @@ -56,24 +102,49 @@ BOOL LLIMFloaterContainer::postBuild()  	mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLIMFloaterContainer::onNewMessageReceived, this, _1));  	// Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button  	// mTabContainer will be initialized in LLMultiFloater::addChild() +	 +	setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); + +	mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); +	mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel"); +	mMessagesPane = getChild<LLLayoutPanel>("messages_layout_panel"); +	 +	mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); + +	// CHUI-98 : View Model for conversations +	LLConversationItem* base_item = new LLConversationItem(getRootViewModel()); +	LLFolderView::Params p; +	p.view_model = &mConversationViewModel; +	p.parent_panel = mConversationsListPanel; +	p.rect = mConversationsListPanel->getLocalRect(); +	p.follows.flags = FOLLOWS_ALL; +	p.listener = base_item; +	p.root = NULL; + +	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); +	mConversationsListPanel->addChild(mConversationsRoot); + +	addConversationListItem(LLUUID()); // manually add nearby chat + +	mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); +	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); + +	childSetAction("add_btn", boost::bind(&LLIMFloaterContainer::onAddButtonClicked, this)); + +	collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); +	collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); +	LLAvatarNameCache::addUseDisplayNamesCallback( +			boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); +  	return TRUE;  }  void LLIMFloaterContainer::onOpen(const LLSD& key)  {  	LLMultiFloater::onOpen(key); -/* -	if (key.isDefined()) -	{ -		LLIMFloater* im_floater = LLIMFloater::findInstance(key.asUUID()); -		if (im_floater) -		{ -			im_floater->openFloater(); -		} -	} -*/  } +// virtual  void LLIMFloaterContainer::addFloater(LLFloater* floaterp,   									BOOL select_added_floater,   									LLTabContainer::eInsertionPoint insertion_point) @@ -86,11 +157,15 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,  		openFloater(floaterp->getKey());  		return;  	} +	 +	// Make sure the message panel is open when adding a floater or it stays mysteriously hidden +	collapseMessagesPane(false); +	// Add the floater  	LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);  	LLUUID session_id = floaterp->getKey(); - +	  	LLIconCtrl* icon = 0;  	if(gAgent.isInGroup(session_id, TRUE)) @@ -113,15 +188,52 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,  		mSessions[session_id] = floaterp;  		floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id));  	} + +	// forced resize of the floater +	LLRect wrapper_rect = this->mTabContainer->getLocalRect(); +	floaterp->setRect(wrapper_rect); +  	mTabContainer->setTabImage(floaterp, icon);  } +  void LLIMFloaterContainer::onCloseFloater(LLUUID& id)  {  	mSessions.erase(id);  	setFocus(TRUE);  } +// virtual +void LLIMFloaterContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height) +{ +	bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); +	bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); + +	S32 conversations_pane_min_dim = mConversationsPane->getMinDim(); + +	if (is_right_pane_expanded) +	{ +		S32 conversations_pane_width = +				(is_left_pane_expanded ? gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") : conversations_pane_min_dim); + +		// possibly increase minimum size constraint due to children's minimums. +		for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +		{ +			LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx)); +			if (floaterp) +			{ +				new_min_width = llmax(new_min_width, +						floaterp->getMinWidth() + conversations_pane_width + LLPANEL_BORDER_WIDTH * 2); +				new_min_height = llmax(new_min_height, floaterp->getMinHeight()); +			} +		} +	} +	else +	{ +		new_min_width = conversations_pane_min_dim; +	} +} +  void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data)  {  	LLUUID session_id = data["session_id"].asUUID(); @@ -136,6 +248,21 @@ void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data)  	}  } +void LLIMFloaterContainer::onExpandCollapseButtonClicked() +{ +	if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() +			&& gSavedPerAccountSettings.getBOOL("ConversationsExpandMessagePaneFirst")) +	{ +		// Expand the messages pane from ultra minimized state +		// if it was collapsed last in order. +		collapseMessagesPane(false); +	} +	else +	{ +		collapseConversationsPane(!mConversationsPane->isCollapsed()); +	} +} +  LLIMFloaterContainer* LLIMFloaterContainer::findInstance()  {  	return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container"); @@ -151,8 +278,6 @@ void LLIMFloaterContainer::setMinimized(BOOL b)  	if (isMinimized() == b) return;  	LLMultiFloater::setMinimized(b); -	// Hide minimized floater (see EXT-5315) -	setVisible(!b);  	if (isMinimized()) return; @@ -162,4 +287,256 @@ void LLIMFloaterContainer::setMinimized(BOOL b)  	}  } +void LLIMFloaterContainer::draw() +{ +	if (mTabContainer->getTabCount() == 0) +	{ +		// Do not close the container when every conversation is torn off because the user +		// still needs the conversation list. Simply collapse the message pane in that case. +		collapseMessagesPane(true); +	} +	LLFloater::draw(); + +	repositioningWidgets(); +} + +void LLIMFloaterContainer::tabClose() +{ +	if (mTabContainer->getTabCount() == 0) +	{ +		// Do not close the container when every conversation is torn off because the user +		// still needs the conversation list. Simply collapse the message pane in that case. +		collapseMessagesPane(true); +	} +} + +void LLIMFloaterContainer::setVisible(BOOL visible) +{ +	if (visible) +	{ +		// Make sure we have the Nearby Chat present when showing the conversation container +		LLIMConversation* nearby_chat = LLIMConversation::findConversation(LLUUID::null); +		if (nearby_chat == NULL) +		{ +			// If not found, force the creation of the nearby chat conversation panel +			// *TODO: find a way to move this to XML as a default panel or something like that +			LLSD name("chat_bar"); +			LLFloaterReg::toggleInstanceOrBringToFront(name, LLSD(LLUUID::null)); +		} +	} + +	// We need to show/hide all the associated conversations that have been torn off +	// (and therefore, are not longer managed by the multifloater), +	// so that they show/hide with the conversations manager. +	conversations_widgets_map::iterator item_it = mConversationsWidgets.begin(); +	for (;item_it != mConversationsWidgets.end(); ++item_it) +	{ +		LLConversationViewSession* item = dynamic_cast<LLConversationViewSession*>(item_it->second); +		item->setVisibleIfDetached(visible); +	} +	 +	// Now, do the normal multifloater show/hide +	LLMultiFloater::setVisible(visible); +	 +} + +void LLIMFloaterContainer::collapseMessagesPane(bool collapse) +{ +	if (mMessagesPane->isCollapsed() == collapse) +	{ +		return; +	} + +	if (collapse) +	{ +		// Save the messages pane width before collapsing it. +		gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", mMessagesPane->getRect().getWidth()); + +		// Save the order in which the panels are closed to reverse user's last action. +		gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); +	} + +	// Show/hide the messages pane. +	mConversationsStack->collapsePanel(mMessagesPane, collapse); + +	updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); +} + +void LLIMFloaterContainer::collapseConversationsPane(bool collapse) +{ +	if (mConversationsPane->isCollapsed() == collapse) +	{ +		return; +	} + +	LLView* button_panel = getChild<LLView>("conversations_pane_buttons_expanded"); +	button_panel->setVisible(!collapse); +	mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); + +	if (collapse) +	{ +		// Save the conversations pane width before collapsing it. +		gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", mConversationsPane->getRect().getWidth()); + +		// Save the order in which the panels are closed to reverse user's last action. +		gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", !mMessagesPane->isCollapsed()); +	} + +	mConversationsStack->collapsePanel(mConversationsPane, collapse); + +	S32 collapsed_width = mConversationsPane->getMinDim(); +	updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); +} + +void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) +{ +	LLRect floater_rect = getRect(); +	floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); + +	// Set by_user = true so that reshaped rect is saved in user_settings. +	setShape(floater_rect, true); + +	updateResizeLimits(); + +	bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); +	bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); + +	setCanResize(is_left_pane_expanded || is_right_pane_expanded); +	setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); + +    // restore floater's resize limits (prevent collapse when left panel is expanded) +	if (is_left_pane_expanded && !is_right_pane_expanded) +	{ +		S32 expanded_min_size = mConversationsPane->getExpandedMinDim(); +        setResizeLimits(expanded_min_size, expanded_min_size); +	} + +} + +void LLIMFloaterContainer::onAddButtonClicked() +{ +    LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE); +    LLFloater* root_floater = gFloaterView->getParentFloater(this); +    if (picker && root_floater) +    { +        root_floater->addDependentFloater(picker); +    } +} + +void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) +{ +    if (ids.size() == 1) +    { +        LLAvatarActions::startIM(ids.back()); +    } +    else +    { +        LLAvatarActions::startConference(ids); +    } +} + +void LLIMFloaterContainer::repositioningWidgets() +{ +	LLRect panel_rect = mConversationsListPanel->getRect(); +	S32 item_height = 16; +	int index = 0; +	for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); +		 widget_it != mConversationsWidgets.end(); +		 widget_it++, ++index) +	{ +		LLFolderViewItem* widget = widget_it->second; +		widget->setVisible(TRUE); +		widget->setRect(LLRect(0, +							   panel_rect.getHeight() - item_height*index, +							   panel_rect.getWidth(), +							   panel_rect.getHeight() - item_height*(index+1))); +	} +} + +// CHUI-137 : Temporary implementation of conversations list +void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) +{ +	std::string display_name = uuid.isNull()? LLTrans::getString("NearbyChatTitle") : LLIMModel::instance().getName(uuid); + +	// Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) +	// Note: this happens often, when reattaching a torn off conversation for instance +	conversations_items_map::iterator item_it = mConversationsItems.find(uuid); +	if (item_it != mConversationsItems.end()) +	{ +		return; +	} + +	// Remove the conversation item that might exist already: it'll be recreated anew further down anyway +	// and nothing wrong will happen removing it if it doesn't exist +	removeConversationListItem(uuid,false); + +	// Create a conversation item +	LLConversationItem* item = new LLConversationItem(display_name, uuid, getRootViewModel()); +	mConversationsItems[uuid] = item; + +	// Create a widget from it +	LLFolderViewItem* widget = createConversationItemWidget(item); +	mConversationsWidgets[uuid] = widget; + +	// Add a new conversation widget to the root folder of a folder view. +	widget->addToFolder(mConversationsRoot); + +	// Add it to the UI +	widget->setVisible(TRUE); + +	repositioningWidgets(); +	 +	mConversationsListPanel->addChild(widget); + +	return; +} + +void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) +{ +	// Delete the widget and the associated conversation item +	// Note : since the mConversationsItems is also the listener to the widget, deleting  +	// the widget will also delete its listener +	conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(uuid); +	if (widget_it != mConversationsWidgets.end()) +	{ +		LLFolderViewItem* widget = widget_it->second; +		widget->destroyView(); +	} +	 +	// Suppress the conversation items and widgets from their respective maps +	mConversationsItems.erase(uuid); +	mConversationsWidgets.erase(uuid); + +	repositioningWidgets(); +	 +	// Don't let the focus fall IW, select and refocus on the first conversation in the list +	if (change_focus) +	{ +		setFocus(TRUE); +		conversations_items_map::iterator item_it = mConversationsItems.begin(); +		if (item_it != mConversationsItems.end()) +		{ +			LLConversationItem* item = item_it->second; +			item->selectItem(); +		} +	} +} + +LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) +{ +	LLConversationViewSession::Params params; +	 +	params.name = item->getDisplayName(); +	//params.icon = bridge->getIcon(); +	//params.icon_open = bridge->getOpenIcon(); +	//params.creation_date = bridge->getCreationDate(); +	params.root = mConversationsRoot; +	params.listener = item; +	params.rect = LLRect (0, 0, 0, 0); +	params.tool_tip = params.name; +	params.container = this; +	 +	return LLUICtrlFactory::create<LLConversationViewSession>(params); +} +  // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 892ecef48d..d6dda8ea2d 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -30,14 +30,23 @@  #include <map>  #include <vector> +#include "llimview.h"  #include "llfloater.h"  #include "llmultifloater.h"  #include "llavatarpropertiesprocessor.h"  #include "llgroupmgr.h" +#include "lltrans.h" +#include "llconversationmodel.h" +class LLButton; +class LLLayoutPanel; +class LLLayoutStack;  class LLTabContainer; +class LLIMFloaterContainer; -class LLIMFloaterContainer : public LLMultiFloater +class LLIMFloaterContainer +	: public LLMultiFloater +	, public LLIMSessionObserver  {  public:  	LLIMFloaterContainer(const LLSD& seed); @@ -45,12 +54,16 @@ public:  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ void draw(); +	/*virtual*/ void setVisible(BOOL visible);  	void onCloseFloater(LLUUID& id);  	/*virtual*/ void addFloater(LLFloater* floaterp,   								BOOL select_added_floater,   								LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); +	/*virtual*/ void tabClose(); +  	static LLFloater* getCurrentVoiceFloater();  	static LLIMFloaterContainer* findInstance(); @@ -59,12 +72,55 @@ public:  	virtual void setMinimized(BOOL b); +	void collapseMessagesPane(bool collapse); +	 + +	// LLIMSessionObserver observe triggers +	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	/*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); +	/*virtual*/ void sessionRemoved(const LLUUID& session_id); +	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); + +	LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } +  private:  	typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t;  	avatarID_panel_map_t mSessions;  	boost::signals2::connection mNewMessageConnection; +	/*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height); +  	void onNewMessageReceived(const LLSD& data); + +	void onExpandCollapseButtonClicked(); + +	void collapseConversationsPane(bool collapse); + +	void updateState(bool collapse, S32 delta_width); +	void repositioningWidgets(); + +	void onAddButtonClicked(); +	void onAvatarPicked(const uuid_vec_t& ids); + +	LLButton* mExpandCollapseBtn; +	LLLayoutPanel* mMessagesPane; +	LLLayoutPanel* mConversationsPane; +	LLLayoutStack* mConversationsStack; +	 +	// Conversation list implementation +public: +	void removeConversationListItem(const LLUUID& uuid, bool change_focus = true); +	void addConversationListItem(const LLUUID& uuid); + +private: +	LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); + +	// Conversation list data +	LLPanel* mConversationsListPanel;	// This is the main widget we add conversation widget to +	conversations_items_map mConversationsItems; +	conversations_widgets_map mConversationsWidgets; +	LLConversationViewModel mConversationViewModel; +	LLFolderView* mConversationsRoot;  };  #endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 07d73c8c66..047472a282 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -37,10 +37,9 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLIMHandler::LLIMHandler(e_notification_type type, const LLSD& id) +LLIMHandler::LLIMHandler() +:	LLSysHandler("IM Notifications", "notifytoast")  { -	mType = type; -  	// Getting a Channel for our notifications  	mChannel = LLChannelManager::getInstance()->createNotificationChannel()->getHandle();  } @@ -59,72 +58,49 @@ void LLIMHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLIMHandler::processNotification(const LLSD& notify) +bool LLIMHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{ -		LLSD substitutions = notification->getSubstitutions(); - -		// According to comments in LLIMMgr::addMessage(), if we get message -		// from ourselves, the sender id is set to null. This fixes EXT-875. -		LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); -		if (avatar_id.isNull()) -			avatar_id = gAgentID; - -		LLToastIMPanel::Params im_p; -		im_p.notification = notification; -		im_p.avatar_id = avatar_id; -		im_p.from = substitutions["FROM"].asString(); -		im_p.time = substitutions["TIME"].asString(); -		im_p.message = substitutions["MESSAGE"].asString(); -		im_p.session_id = substitutions["SESSION_ID"].asUUID(); - -		LLToastIMPanel* im_box = new LLToastIMPanel(im_p); - -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.session_id = im_p.session_id; -		p.notification = notification; -		p.panel = im_box; -		p.can_be_stored = false; -		p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); - -		// send a signal to the counter manager; -		mNewNotificationSignal(); -	} -	else if (notify["sigtype"].asString() == "delete") -	{ -		mChannel.get()->killToastByNotificationID(notification->getID()); -	} -	return false; -} +	LLSD substitutions = notification->getSubstitutions(); + +	// According to comments in LLIMMgr::addMessage(), if we get message +	// from ourselves, the sender id is set to null. This fixes EXT-875. +	LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); +	if (avatar_id.isNull()) +		avatar_id = gAgentID; + +	LLToastIMPanel::Params im_p; +	im_p.notification = notification; +	im_p.avatar_id = avatar_id; +	im_p.from = substitutions["FROM"].asString(); +	im_p.time = substitutions["TIME"].asString(); +	im_p.message = substitutions["MESSAGE"].asString(); +	im_p.session_id = substitutions["SESSION_ID"].asUUID(); + +	LLToastIMPanel* im_box = new LLToastIMPanel(im_p); + +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.session_id = im_p.session_id; +	p.notification = notification; +	p.panel = im_box; +	p.can_be_stored = false; +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); -//-------------------------------------------------------------------------- -void LLIMHandler::onDeleteToast(LLToast* toast) -{ -	// send a signal to the counter manager -	mDelNotificationSignal(); +	return false;  } -//-------------------------------------------------------------------------- diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4000570872..d88a558125 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -41,7 +41,7 @@  #include "lltextutil.h"  #include "lltrans.h"  #include "lluictrlfactory.h" - +#include "llimconversation.h"  #include "llagent.h"  #include "llagentui.h"  #include "llappviewer.h" @@ -175,10 +175,11 @@ LLIMModel::LLIMModel()  	addNewMsgCallback(boost::bind(&toast_callback, _1));  } -LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice) +LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg)  :	mSessionID(session_id),  	mName(name),  	mType(type), +	mHasOfflineMessage(has_offline_msg),  	mParticipantUnreadMessageCount(0),  	mNumUnread(0),  	mOtherParticipantID(other_participant_id), @@ -375,6 +376,8 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  				break;  			}  		} +	default: +		break;  	}  	// Update speakers list when connected  	if (LLVoiceChannel::STATE_CONNECTED == new_state) @@ -676,7 +679,7 @@ void LLIMModel::testMessages()  //session name should not be empty  bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,  -						   const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice) +						   const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg)  {  	if (name.empty())  	{ @@ -690,7 +693,7 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co  		return false;  	} -	LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice); +	LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice, has_offline_msg);  	mId2SessionMap[session_id] = session;  	// When notifying observer, name of session is used instead of "name", because they may not be the @@ -702,10 +705,10 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co  } -bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice) +bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice, bool has_offline_msg)  {  	uuid_vec_t no_ids; -	return newSession(session_id, name, type, other_participant_id, no_ids, voice); +	return newSession(session_id, name, type, other_participant_id, no_ids, voice, has_offline_msg);  }  bool LLIMModel::clearSession(const LLUUID& session_id) @@ -716,6 +719,16 @@ bool LLIMModel::clearSession(const LLUUID& session_id)  	return true;  } +void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index, const bool sendNoUnreadMsgs) +{ +	getMessagesSilently(session_id, messages, start_index); + +	if (sendNoUnreadMsgs) +	{ +		sendNoUnreadMessages(session_id); +	} +} +  void LLIMModel::getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)  {  	LLIMSession* session = findIMSession(session_id); @@ -757,13 +770,6 @@ void LLIMModel::sendNoUnreadMessages(const LLUUID& session_id)  	mNoUnreadMsgsSignal(arg);  } -void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index) -{ -	getMessagesSilently(session_id, messages, start_index); - -	sendNoUnreadMessages(session_id); -} -  bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {  	LLIMSession* session = findIMSession(session_id); @@ -904,7 +910,7 @@ const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const  	LLIMSession* session = findIMSession(session_id);  	if (!session)  	{ -		llwarns << "session " << session_id << "does not exist " << llendl; +		llwarns << "session " << session_id << " does not exist " << llendl;  		return LLUUID::null;  	} @@ -2395,6 +2401,7 @@ void LLIMMgr::addMessage(  	const LLUUID& target_id,  	const std::string& from,  	const std::string& msg, +	bool  is_offline_msg,  	const std::string& session_name,  	EInstantMessage dialog,  	U32 parent_estate_id, @@ -2420,7 +2427,7 @@ void LLIMMgr::addMessage(  	bool new_session = !hasSession(new_session_id);  	if (new_session)  	{ -		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id); +		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg);  		// When we get a new IM, and if you are a god, display a bit  		// of information about the source. This is to help liaisons @@ -2480,8 +2487,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess  		LLChat chat(message);  		chat.mSourceType = CHAT_SOURCE_SYSTEM; -		LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); -		LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); +		LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();  		if(nearby_chat)  		{ @@ -2497,6 +2503,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess  			gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString());  		}  		// log message to file +  		else  		{  			std::string session_name; @@ -2579,7 +2586,8 @@ LLUUID LLIMMgr::addSession(  {  	LLDynamicArray<LLUUID> ids;  	ids.put(other_participant_id); -	return addSession(name, dialog, other_participant_id, ids, voice); +	LLUUID session_id = addSession(name, dialog, other_participant_id, ids, voice); +	return session_id;  }  // Adds a session using the given session_id.  If the session already exists  @@ -2588,7 +2596,8 @@ LLUUID LLIMMgr::addSession(  	const std::string& name,  	EInstantMessage dialog,  	const LLUUID& other_participant_id, -	const LLDynamicArray<LLUUID>& ids, bool voice) +	const LLDynamicArray<LLUUID>& ids, bool voice, +	const LLUUID& floater_id)  {  	if (0 == ids.getLength())  	{ @@ -2603,6 +2612,19 @@ LLUUID LLIMMgr::addSession(  	LLUUID session_id = computeSessionID(dialog,other_participant_id); +	if (floater_id.notNull()) +	{ +		LLIMFloater* im_floater = LLIMFloater::findInstance(floater_id); + +		if (im_floater && im_floater->getStartConferenceInSameFloater()) +		{ +			// The IM floater should be initialized with a new session_id +			// so that it is found by that id when creating a chiclet in LLIMFloater::onIMChicletCreated, +			// and a new floater is not created. +			im_floater->initIMSession(session_id); +		} +	} +  	bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);  	//works only for outgoing ad-hoc sessions @@ -2634,6 +2656,8 @@ LLUUID LLIMMgr::addSession(  		noteMutedUsers(session_id, ids);  	} +	notifyObserverSessionVoiceOrIMStarted(session_id); +  	return session_id;  } @@ -2920,6 +2944,14 @@ void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::st  	}  } +void LLIMMgr::notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id) +{ +	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) +	{ +		(*it)->sessionVoiceOrIMStarted(session_id); +	} +} +  void LLIMMgr::notifyObserverSessionRemoved(const LLUUID& session_id)  {  	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) @@ -3279,6 +3311,7 @@ public:  				from_id,  				name,  				buffer, +				IM_OFFLINE == offline,  				std::string((char*)&bin_bucket[0]),  				IM_SESSION_INVITE,  				message_params["parent_estate_id"].asInteger(), diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 7c2cd03d97..fa9d20ca53 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -70,10 +70,11 @@ public:  			GROUP_SESSION,  			ADHOC_SESSION,  			AVALINE_SESSION, +			NONE_SESSION,  		} SType;  		LLIMSession(const LLUUID& session_id, const std::string& name,  -			const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice); +			const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg);  		virtual ~LLIMSession();  		void sessionInitReplyReceived(const LLUUID& new_session_id); @@ -133,6 +134,8 @@ public:  		//if IM session is created for a voice call  		bool mStartedAsIMCall; +		bool mHasOfflineMessage; +  	private:  		void onAdHocNameCache(const LLAvatarName& av_name); @@ -181,10 +184,10 @@ public:  	 * @param name session name should not be empty, will return false if empty  	 */  	bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id,  -		const uuid_vec_t& ids, bool voice = false); +		const uuid_vec_t& ids, bool voice = false, bool has_offline_msg = false);  	bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, -		const LLUUID& other_participant_id, bool voice = false); +		const LLUUID& other_participant_id, bool voice = false, bool has_offline_msg = false);  	/**  	 * Remove all session data associated with a session specified by session_id @@ -192,12 +195,6 @@ public:  	bool clearSession(const LLUUID& session_id);  	/** -	 * Populate supplied std::list with messages starting from index specified by start_index without -	 * emitting no unread messages signal. -	 */ -	void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); - -	/**  	 * Sends no unread messages signal.  	 */  	void sendNoUnreadMessages(const LLUUID& session_id); @@ -205,7 +202,7 @@ public:  	/**  	 * Populate supplied std::list with messages starting from index specified by start_index  	 */ -	void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); +	void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0, const bool sendNoUnreadMsgs = true);  	/**  	 * Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id @@ -288,6 +285,12 @@ public:  private:  	/** +	 * Populate supplied std::list with messages starting from index specified by start_index without +	 * emitting no unread messages signal. +	 */ +	void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); + +	/**  	 * Add message to a list of message associated with session specified by session_id  	 */  	bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text); @@ -298,6 +301,7 @@ class LLIMSessionObserver  public:  	virtual ~LLIMSessionObserver() {}  	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; +	virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) = 0;  	virtual void sessionRemoved(const LLUUID& session_id) = 0;  	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) = 0;  }; @@ -324,6 +328,7 @@ public:  					const LLUUID& target_id,  					const std::string& from,  					const std::string& msg, +					bool  is_offline_msg = false,  					const std::string& session_name = LLStringUtil::null,  					EInstantMessage dialog = IM_NOTHING_SPECIAL,  					U32 parent_estate_id = 0, @@ -347,10 +352,12 @@ public:  	// Adds a session using a specific group of starting agents  	// the dialog type is assumed correct. Returns the uuid of the session. +	// A session can be added to a floater specified by floater_id.  	LLUUID addSession(const std::string& name,  					  EInstantMessage dialog,  					  const LLUUID& other_participant_id, -					  const LLDynamicArray<LLUUID>& ids, bool voice = false); +					  const LLDynamicArray<LLUUID>& ids, bool voice = false, +					  const LLUUID& floater_id = LLUUID::null);  	/**  	 * Creates a P2P session with the requisite handle for responding to voice calls. @@ -460,6 +467,7 @@ private:  	static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group);  	void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	void notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id);  	void notifyObserverSessionRemoved(const LLUUID& session_id);  	void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 17d0b0ffbb..8a15cd279f 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -28,38 +28,21 @@  #include "llinspectavatar.h"  // viewer files -#include "llagent.h" -#include "llagentdata.h" -#include "llavataractions.h" +#include "llavatariconctrl.h"  #include "llavatarnamecache.h"  #include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h"  #include "lldateutil.h" -#include "llfloaterreporter.h" -#include "llfloaterworldmap.h" -#include "llimview.h"  #include "llinspect.h" -#include "llmutelist.h" -#include "llpanelblockedlist.h" +#include "llslurl.h"  #include "llstartup.h" -#include "llspeakers.h" -#include "llviewermenu.h" -#include "llvoiceclient.h" -#include "llviewerobjectlist.h"  #include "lltransientfloatermgr.h" -#include "llnotificationsutil.h"  // Linden libraries  #include "llfloater.h"  #include "llfloaterreg.h" -#include "llmenubutton.h"  #include "lltextbox.h" -#include "lltoggleablemenu.h"  #include "lltooltip.h"	// positionViewNearMouse()  #include "lltrans.h" -#include "lluictrl.h" - -#include "llavatariconctrl.h"  class LLFetchAvatarData; @@ -81,22 +64,13 @@ public:  	LLInspectAvatar(const LLSD& avatar_id);  	virtual ~LLInspectAvatar(); -	/*virtual*/ BOOL postBuild(void); -	  	// Because floater is single instance, need to re-parse data on each spawn  	// (for example, inspector about same avatar but in different position)  	/*virtual*/ void onOpen(const LLSD& avatar_id); -	// When closing they should close their gear menu  -	/*virtual*/ void onClose(bool app_quitting); -	  	// Update view based on information from avatar properties processor  	void processAvatarData(LLAvatarData* data); -	// override the inspector mouse leave so timer is only paused if  -	// gear menu is not open -	/* virtual */ void onMouseLeave(S32 x, S32 y, MASK mask); -	  	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; }  private: @@ -104,47 +78,6 @@ private:  	// Used on construction and if avatar id changes.  	void requestUpdate(); -	// Set the volume slider to this user's current client-side volume setting, -	// hiding/disabling if the user is not nearby. -	void updateVolumeSlider(); - -	// Shows/hides moderator panel depending on voice state  -	void updateModeratorPanel(); - -	// Moderator ability to enable/disable voice chat for avatar -	void toggleSelectedVoice(bool enabled); -	 -	// Button callbacks -	void onClickAddFriend(); -	void onClickViewProfile(); -	void onClickIM(); -	void onClickCall(); -	void onClickTeleport(); -	void onClickInviteToGroup(); -	void onClickPay(); -	void onClickShare(); -	void onToggleMute(); -	void onClickReport(); -	void onClickFreeze(); -	void onClickEject(); -	void onClickKick(); -	void onClickCSR(); -	void onClickZoomIn();   -	void onClickFindOnMap(); -	bool onVisibleFindOnMap(); -	bool onVisibleEject(); -	bool onVisibleFreeze(); -	bool onVisibleZoomIn(); -	void onClickMuteVolume(); -	void onVolumeChange(const LLSD& data); -	bool enableMute(); -	bool enableUnmute(); -	bool enableTeleportOffer(); -	bool godModeEnabled(); - -	// Is used to determine if "Add friend" option should be enabled in gear menu -	bool isNotFriend(); -	  	void onAvatarNameCache(const LLUUID& agent_id,  						   const LLAvatarName& av_name); @@ -209,39 +142,8 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd)  	mAvatarName(),  	mPropertiesRequest(NULL)  { -	mCommitCallbackRegistrar.add("InspectAvatar.ViewProfile",	boost::bind(&LLInspectAvatar::onClickViewProfile, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.AddFriend",	boost::bind(&LLInspectAvatar::onClickAddFriend, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.IM", -		boost::bind(&LLInspectAvatar::onClickIM, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Call",		boost::bind(&LLInspectAvatar::onClickCall, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Teleport",	boost::bind(&LLInspectAvatar::onClickTeleport, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.InviteToGroup",	boost::bind(&LLInspectAvatar::onClickInviteToGroup, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Pay",	boost::bind(&LLInspectAvatar::onClickPay, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Share",	boost::bind(&LLInspectAvatar::onClickShare, this)); -	mCommitCallbackRegistrar.add("InspectAvatar.ToggleMute",	boost::bind(&LLInspectAvatar::onToggleMute, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Freeze", boost::bind(&LLInspectAvatar::onClickFreeze, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Eject", boost::bind(&LLInspectAvatar::onClickEject, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Kick", boost::bind(&LLInspectAvatar::onClickKick, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.CSR", boost::bind(&LLInspectAvatar::onClickCSR, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Report",	boost::bind(&LLInspectAvatar::onClickReport, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.FindOnMap",	boost::bind(&LLInspectAvatar::onClickFindOnMap, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.ZoomIn", boost::bind(&LLInspectAvatar::onClickZoomIn, this)); -	mCommitCallbackRegistrar.add("InspectAvatar.DisableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, false)); -	mCommitCallbackRegistrar.add("InspectAvatar.EnableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, true)); - -	mEnableCallbackRegistrar.add("InspectAvatar.EnableGod",	boost::bind(&LLInspectAvatar::godModeEnabled, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap",	boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleEject",	boost::bind(&LLInspectAvatar::onVisibleEject, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleFreeze",	boost::bind(&LLInspectAvatar::onVisibleFreeze, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleZoomIn", boost::bind(&LLInspectAvatar::onVisibleZoomIn, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.Gear.Enable", boost::bind(&LLInspectAvatar::isNotFriend, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableCall", boost::bind(&LLAvatarActions::canCall)); -	mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableTeleportOffer", boost::bind(&LLInspectAvatar::enableTeleportOffer, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.EnableMute", boost::bind(&LLInspectAvatar::enableMute, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.EnableUnmute", boost::bind(&LLInspectAvatar::enableUnmute, this)); -  	// can't make the properties request until the widgets are constructed -	// as it might return immediately, so do it in postBuild. +	// as it might return immediately, so do it in onOpen.  	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this);  	LLTransientFloater::init(this); @@ -257,25 +159,6 @@ LLInspectAvatar::~LLInspectAvatar()  	LLTransientFloaterMgr::getInstance()->removeControlView(this);  } -/*virtual*/ -BOOL LLInspectAvatar::postBuild(void) -{ -	getChild<LLUICtrl>("add_friend_btn")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onClickAddFriend, this) ); - -	getChild<LLUICtrl>("view_profile_btn")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onClickViewProfile, this) ); - -	getChild<LLUICtrl>("mute_btn")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onClickMuteVolume, this) ); - -	getChild<LLUICtrl>("volume_slider")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onVolumeChange, this, _2)); - -	return TRUE; -} - -  // Multiple calls to showInstance("inspect_avatar", foo) will provide different  // LLSD for foo, which we will catch here.  //virtual @@ -287,11 +170,6 @@ void LLInspectAvatar::onOpen(const LLSD& data)  	// Extract appropriate avatar id  	mAvatarID = data["avatar_id"]; -	BOOL self = mAvatarID == gAgent.getID(); -	 -	getChild<LLUICtrl>("gear_self_btn")->setVisible(self); -	getChild<LLUICtrl>("gear_btn")->setVisible(!self); -  	// Position the inspector relative to the mouse cursor  	// Similar to how tooltips are positioned  	// See LLToolTipMgr::createToolTip @@ -304,20 +182,13 @@ void LLInspectAvatar::onOpen(const LLSD& data)  		LLUI::positionViewNearMouse(this);  	} +	// Generate link to avatar profile. +	getChild<LLUICtrl>("avatar_profile_link")->setTextArg("[LINK]", LLSLURL("agent", mAvatarID, "about").getSLURLString()); +  	// can't call from constructor as widgets are not built yet  	requestUpdate(); - -	updateVolumeSlider(); - -	updateModeratorPanel();  } -// virtual -void LLInspectAvatar::onClose(bool app_quitting) -{   -  getChild<LLMenuButton>("gear_btn")->hideMenu(); -}	 -  void LLInspectAvatar::requestUpdate()  {  	// Don't make network requests when spawning from the debug menu at the @@ -344,25 +215,6 @@ void LLInspectAvatar::requestUpdate()  	delete mPropertiesRequest;  	mPropertiesRequest = new LLFetchAvatarData(mAvatarID, this); -	// You can't re-add someone as a friend if they are already your friend -	bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL; -	bool is_self = (mAvatarID == gAgentID); -	if (is_self) -	{ -		getChild<LLUICtrl>("add_friend_btn")->setVisible(false); -		getChild<LLUICtrl>("im_btn")->setVisible(false); -	} -	else if (is_friend) -	{ -		getChild<LLUICtrl>("add_friend_btn")->setVisible(false); -		getChild<LLUICtrl>("im_btn")->setVisible(true); -	} -	else -	{ -		getChild<LLUICtrl>("add_friend_btn")->setVisible(true); -		getChild<LLUICtrl>("im_btn")->setVisible(false); -	} -  	// Use an avatar_icon even though the image id will come down with the  	// avatar properties because the avatar_icon code maintains a cache of icons  	// and this may result in the image being visible sooner. @@ -405,214 +257,6 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)  	mPropertiesRequest = NULL;  } -// For the avatar inspector, we only want to unpause the fade timer  -// if neither the gear menu or self gear menu are open -void LLInspectAvatar::onMouseLeave(S32 x, S32 y, MASK mask) -{ -	LLToggleableMenu* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu(); -	LLToggleableMenu* gear_menu_self = getChild<LLMenuButton>("gear_self_btn")->getMenu(); -	if ( gear_menu && gear_menu->getVisible() && -		 gear_menu_self && gear_menu_self->getVisible() ) -	{ -		return; -	} - -	if(childHasVisiblePopupMenu()) -	{ -		return; -	} - -	mOpenTimer.unpause(); -} - -void LLInspectAvatar::updateModeratorPanel() -{ -	bool enable_moderator_panel = false; - -    if (LLVoiceChannel::getCurrentVoiceChannel() && -		mAvatarID != gAgent.getID()) -    { -		LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID(); - -		if (session_id != LLUUID::null) -		{ -			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - -			if (speaker_mgr) -			{ -				LLPointer<LLSpeaker> self_speakerp = speaker_mgr->findSpeaker(gAgent.getID()); -				LLPointer<LLSpeaker> selected_speakerp = speaker_mgr->findSpeaker(mAvatarID); -				 -				if(speaker_mgr->isVoiceActive() && selected_speakerp &&  -					selected_speakerp->isInVoiceChannel() && -					((self_speakerp && self_speakerp->mIsModerator) || gAgent.isGodlike())) -				{ -					getChild<LLUICtrl>("enable_voice")->setVisible(selected_speakerp->mModeratorMutedVoice); -					getChild<LLUICtrl>("disable_voice")->setVisible(!selected_speakerp->mModeratorMutedVoice); - -					enable_moderator_panel = true; -				} -			} -		} -	} - -	if (enable_moderator_panel) -	{ -		if (!getChild<LLUICtrl>("moderator_panel")->getVisible()) -		{ -			getChild<LLUICtrl>("moderator_panel")->setVisible(true); -			// stretch the floater so it can accommodate the moderator panel -			reshape(getRect().getWidth(), getRect().getHeight() + getChild<LLUICtrl>("moderator_panel")->getRect().getHeight()); -		} -	} -	else if (getChild<LLUICtrl>("moderator_panel")->getVisible()) -	{ -		getChild<LLUICtrl>("moderator_panel")->setVisible(false); -		// shrink the inspector floater back to original size -		reshape(getRect().getWidth(), getRect().getHeight() - getChild<LLUICtrl>("moderator_panel")->getRect().getHeight());					 -	} -} - -void LLInspectAvatar::toggleSelectedVoice(bool enabled) -{ -	LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID(); -	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - -	if (speaker_mgr) -	{ -		if (!gAgent.getRegion()) -			return; - -		std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); -		LLSD data; -		data["method"] = "mute update"; -		data["session-id"] = session_id; -		data["params"] = LLSD::emptyMap(); -		data["params"]["agent_id"] = mAvatarID; -		data["params"]["mute_info"] = LLSD::emptyMap(); -		// ctrl value represents ability to type, so invert -		data["params"]["mute_info"]["voice"] = !enabled; - -		class MuteVoiceResponder : public LLHTTPClient::Responder -		{ -		public: -			MuteVoiceResponder(const LLUUID& session_id) -			{ -				mSessionID = session_id; -			} - -			virtual void error(U32 status, const std::string& reason) -			{ -				llwarns << status << ": " << reason << llendl; - -				if ( gIMMgr ) -				{ -					//403 == you're not a mod -					//should be disabled if you're not a moderator -					if ( 403 == status ) -					{ -						gIMMgr->showSessionEventError( -							"mute", -							"not_a_moderator", -							mSessionID); -					} -					else -					{ -						gIMMgr->showSessionEventError( -							"mute", -							"generic", -							mSessionID); -					} -				} -			} - -		private: -			LLUUID mSessionID; -		}; - -		LLHTTPClient::post( -			url, -			data, -			new MuteVoiceResponder(speaker_mgr->getSessionID())); -	} - -	closeFloater(); - -} - -void LLInspectAvatar::updateVolumeSlider() -{ -	bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); - -	// Do not display volume slider and mute button if it  -	// is ourself or we are not in a voice channel together -	if (!voice_enabled || (mAvatarID == gAgent.getID())) -	{ -		getChild<LLUICtrl>("mute_btn")->setVisible(false); -		getChild<LLUICtrl>("volume_slider")->setVisible(false); -	} - -	else  -	{ -		getChild<LLUICtrl>("mute_btn")->setVisible(true); -		getChild<LLUICtrl>("volume_slider")->setVisible(true); - -		// By convention, we only display and toggle voice mutes, not all mutes -		bool is_muted = LLMuteList::getInstance()-> -							isMuted(mAvatarID, LLMute::flagVoiceChat); - -		LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); - -		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); - -		mute_btn->setEnabled( !is_linden); -		mute_btn->setValue( is_muted ); - -		LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); -		volume_slider->setEnabled( !is_muted ); - -		F32 volume; -		 -		if (is_muted) -		{ -			// it's clearer to display their volume as zero -			volume = 0.f; -		} -		else -		{ -			// actual volume -			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); -		} -		volume_slider->setValue( (F64)volume ); -	} - -} - -void LLInspectAvatar::onClickMuteVolume() -{ -	// By convention, we only display and toggle voice mutes, not all mutes -	LLMuteList* mute_list = LLMuteList::getInstance(); -	bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); - -	LLMute mute(mAvatarID, mAvatarName.getLegacyName(), LLMute::AGENT); -	if (!is_muted) -	{ -		mute_list->add(mute, LLMute::flagVoiceChat); -	} -	else -	{ -		mute_list->remove(mute, LLMute::flagVoiceChat); -	} - -	updateVolumeSlider(); -} - -void LLInspectAvatar::onVolumeChange(const LLSD& data) -{ -	F32 volume = (F32)data.asReal(); -	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); -} -  void LLInspectAvatar::onAvatarNameCache(  		const LLUUID& agent_id,  		const LLAvatarName& av_name) @@ -640,215 +284,6 @@ void LLInspectAvatar::onAvatarNameCache(  	}  } -void LLInspectAvatar::onClickAddFriend() -{ -	LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName.getLegacyName()); -	closeFloater(); -} - -void LLInspectAvatar::onClickViewProfile() -{ -	LLAvatarActions::showProfile(mAvatarID); -	closeFloater(); -} - -bool LLInspectAvatar::isNotFriend() -{ -	return !LLAvatarActions::isFriend(mAvatarID); -} - -bool LLInspectAvatar::onVisibleFindOnMap() -{ -	return gAgent.isGodlike() || is_agent_mappable(mAvatarID); -} - -bool LLInspectAvatar::onVisibleEject() -{ -	return enable_freeze_eject( LLSD(mAvatarID) ); -} - -bool LLInspectAvatar::onVisibleFreeze() -{ -	// either user is a god and can do long distance freeze -	// or check for target proximity and permissions -	return gAgent.isGodlike() || enable_freeze_eject(LLSD(mAvatarID)); -} - -bool LLInspectAvatar::onVisibleZoomIn() -{ -	return gObjectList.findObject(mAvatarID); -} - -void LLInspectAvatar::onClickIM() -{  -	LLAvatarActions::startIM(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickCall() -{  -	LLAvatarActions::startCall(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickTeleport() -{ -	LLAvatarActions::offerTeleport(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickInviteToGroup() -{ -	LLAvatarActions::inviteToGroup(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickPay() -{ -	LLAvatarActions::pay(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickShare() -{ -	LLAvatarActions::share(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onToggleMute() -{ -	LLMute mute(mAvatarID, mAvatarName.mDisplayName, LLMute::AGENT); - -	if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName)) -	{ -		LLMuteList::getInstance()->remove(mute); -	} -	else -	{ -		LLMuteList::getInstance()->add(mute); -	} - -	LLPanelBlockedList::showPanelAndSelect(mute.mID); -	closeFloater(); -} - -void LLInspectAvatar::onClickReport() -{ -	LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName.getCompleteName()); -	closeFloater(); -} - -bool godlike_freeze(const LLSD& notification, const LLSD& response) -{ -	LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - -	switch (option) -	{ -	case 0: -		LLAvatarActions::freeze(avatar_id); -		break; -	case 1: -		LLAvatarActions::unfreeze(avatar_id); -		break; -	default: -		break; -	} - -	return false; -} - -void LLInspectAvatar::onClickFreeze() -{ -	if (gAgent.isGodlike()) -	{ -		// use godlike freeze-at-a-distance, with confirmation -		LLNotificationsUtil::add("FreezeAvatar", -			LLSD(), -			LLSD().with("avatar_id", mAvatarID), -			godlike_freeze); -	} -	else -	{ -		// use default "local" version of freezing that requires avatar to be in range -		handle_avatar_freeze( LLSD(mAvatarID) ); -	} -	closeFloater(); -} - -void LLInspectAvatar::onClickEject() -{ -	handle_avatar_eject( LLSD(mAvatarID) ); -	closeFloater(); -} - -void LLInspectAvatar::onClickKick() -{ -	LLAvatarActions::kick(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickCSR() -{ -	std::string name; -	gCacheName->getFullName(mAvatarID, name); -	LLAvatarActions::csr(mAvatarID, name); -	closeFloater(); -} - -void LLInspectAvatar::onClickZoomIn()  -{ -	handle_zoom_to_object(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickFindOnMap() -{ -	gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName.mDisplayName); -	LLFloaterReg::showInstance("world_map"); -} - - -bool LLInspectAvatar::enableMute() -{ -		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); -		bool is_self = mAvatarID == gAgent.getID(); - -		if (!is_linden && !is_self && !LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName())) -		{ -			return true; -		} -		else -		{ -			return false; -		} -} - -bool LLInspectAvatar::enableUnmute() -{ -		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); -		bool is_self = mAvatarID == gAgent.getID(); - -		if (!is_linden && !is_self && LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName())) -		{ -			return true; -		} -		else -		{ -			return false; -		} -} - -bool LLInspectAvatar::enableTeleportOffer() -{ -	return LLAvatarActions::canOfferTeleport(mAvatarID); -} - -bool LLInspectAvatar::godModeEnabled() -{ -	return gAgent.isGodlike(); -} -  //////////////////////////////////////////////////////////////////////////////  // LLInspectAvatarUtil  ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b819100b9b..49a856de61 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -37,6 +37,7 @@  #include "llappearancemgr.h"  #include "llattachmentsmgr.h"  #include "llavataractions.h"  +#include "llfavoritesbar.h" // management of favorites folder  #include "llfloateropenobject.h"  #include "llfloaterreg.h"  #include "llfloatersidepanelcontainer.h" @@ -115,10 +116,10 @@ void teleport_via_landmark(const LLUUID& asset_id);  static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit);  static bool check_category(LLInventoryModel* model,  						   const LLUUID& cat_id, -						   LLFolderView* active_folder_view, +						   LLInventoryPanel* active_panel,  						   LLInventoryFilter* filter);  static bool check_item(const LLUUID& item_id, -					   LLFolderView* active_folder_view, +					   LLInventoryPanel* active_panel,  					   LLInventoryFilter* filter);  // Helper functions @@ -189,7 +190,8 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory,  	mUUID(uuid),   	mRoot(root),  	mInvType(LLInventoryType::IT_NONE), -	mIsLink(FALSE) +	mIsLink(FALSE), +	LLFolderViewModelItemInventory(inventory->getRootViewModel())  {  	mInventoryPanel = inventory->getInventoryPanelHandle();  	const LLInventoryObject* obj = getInventoryObject(); @@ -208,7 +210,11 @@ const std::string& LLInvFVBridge::getName() const  const std::string& LLInvFVBridge::getDisplayName() const  { -	return getName(); +	if(mDisplayName.empty()) +	{ +		buildDisplayName(); +	} +	return mDisplayName;  }  // Folders have full perms @@ -227,9 +233,24 @@ LLFolderType::EType LLInvFVBridge::getPreferredType() const  // Folders don't have creation dates.  time_t LLInvFVBridge::getCreationDate() const  { -	return 0; +	LLInventoryObject* objectp = getInventoryObject(); +	if (objectp) +	{ +		return objectp->getCreationDate(); +	} +	return (time_t)0; +} + +void LLInvFVBridge::setCreationDate(time_t creation_date_utc) +{ +	LLInventoryObject* objectp = getInventoryObject(); +	if (objectp) +	{ +		objectp->setCreationDate(creation_date_utc); +	}  } +  // Can be destroyed (or moved to trash)  BOOL LLInvFVBridge::isItemRemovable() const  { @@ -283,7 +304,7 @@ void LLInvFVBridge::showProperties()  	*/  } -void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch)  {  	// Deactivate gestures when moving them into Trash  	LLInvFVBridge* bridge; @@ -292,11 +313,11 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc  	LLViewerInventoryCategory* cat = NULL;  	LLInventoryModel::cat_array_t	descendent_categories;  	LLInventoryModel::item_array_t	descendent_items; -	S32 count = batch.count(); +	S32 count = batch.size();  	S32 i,j;  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());  		if (item) @@ -309,7 +330,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc  	}  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());  		if (cat) @@ -327,7 +348,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc  	removeBatchNoCheck(batch);  } -void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch) +void  LLInvFVBridge::removeBatchNoCheck(std::vector<LLFolderViewModelItem*>&  batch)  {  	// this method moves a bunch of items and folders to the trash. As  	// per design guidelines for the inventory model, the message is @@ -343,14 +364,14 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*  	uuid_vec_t move_ids;  	LLInventoryModel::update_map_t update;  	bool start_new_message = true; -	S32 count = batch.count(); +	S32 count = batch.size();  	S32 i;  	// first, hide any 'preview' floaters that correspond to the items  	// being deleted.  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());  		if(item) @@ -363,7 +384,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());  		if(item) @@ -404,7 +425,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());  		if(cat) @@ -876,6 +897,12 @@ LLInventoryModel* LLInvFVBridge::getInventoryModel() const  	return panel ? panel->getModel() : NULL;  } +LLInventoryFilter* LLInvFVBridge::getInventoryFilter() const +{ +	LLInventoryPanel* panel = mInventoryPanel.get(); +	return panel ? &(panel->getFilter()) : NULL; +} +  BOOL LLInvFVBridge::isItemInTrash() const  {  	LLInventoryModel* model = getInventoryModel(); @@ -928,7 +955,7 @@ BOOL LLInvFVBridge::isCOFFolder() const  BOOL LLInvFVBridge::isInboxFolder() const  { -	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false); +	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false);  	if (inbox_id.isNull())  	{ @@ -968,7 +995,7 @@ BOOL LLInvFVBridge::isOutboxFolderDirectParent() const  const LLUUID LLInvFVBridge::getOutboxFolder() const  { -	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); +	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);  	return outbox_id;  } @@ -1000,6 +1027,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,  										   LLAssetType::EType actual_asset_type,  										   LLInventoryType::EType inv_type,  										   LLInventoryPanel* inventory, +										   LLFolderViewModelInventory* view_model,  										   LLFolderView* root,  										   const LLUUID& uuid,  										   U32 flags) @@ -1250,10 +1278,10 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  		if (can_list)  		{ -			LLFolderViewFolder * object_folderp = mRoot->getFolderByID(object_id); +			LLFolderViewFolder * object_folderp =   mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL;  			if (object_folderp)  			{ -				can_list = !object_folderp->isLoading(); +				can_list = !static_cast<LLFolderBridge*>(object_folderp->getViewModelItem())->isLoading();  			}  		} @@ -1261,7 +1289,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  		{  			// Get outbox id  			const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); -			LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id); +			LLFolderViewItem * outbox_itemp =   mInventoryPanel.get() ? mInventoryPanel.get()->getItemByID(outbox_id) : NULL;  			if (outbox_itemp)  			{ @@ -1271,7 +1299,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  				void * cargo_data = (void *) obj;  				std::string tooltip_msg; -				can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); +				can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);  			}  		}  	} @@ -1283,14 +1311,30 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  #endif  } +LLToolDragAndDrop::ESource LLInvFVBridge::getDragSource() const +{ +	if (gInventory.isObjectDescendentOf(getUUID(),   gInventory.getRootFolderID())) +	{ +		return LLToolDragAndDrop::SOURCE_AGENT; +	} +	else if (gInventory.isObjectDescendentOf(getUUID(),   gInventory.getLibraryRootFolderID())) +	{ +		return LLToolDragAndDrop::SOURCE_LIBRARY; +	} + +	return LLToolDragAndDrop::SOURCE_VIEWER; +} + +  // +=================================================+  // |        InventoryFVBridgeBuilder                 |  // +=================================================+ -LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, +LLInvFVBridge* LLInventoryFolderViewModelBuilder::createBridge(LLAssetType::EType asset_type,  														LLAssetType::EType actual_asset_type,  														LLInventoryType::EType inv_type,  														LLInventoryPanel* inventory, +														LLFolderViewModelInventory* view_model,  														LLFolderView* root,  														const LLUUID& uuid,  														U32 flags /* = 0x00 */) const @@ -1299,6 +1343,7 @@ LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset  									   actual_asset_type,  									   inv_type,  									   inventory, +									   view_model,  									   root,  									   uuid,  									   flags); @@ -1355,10 +1400,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  	else if ("cut" == action)  	{  		cutToClipboard(); -		// MAINT-1197: This is temp code to work around a deselection/reselection bug. Please discard when merging CHUI. -		LLFolderViewItem* item_to_select = mRoot->getNextUnselectedItem(); -		LLFolderView::removeCutItems(); -		mRoot->setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, false); +		gInventory.removeObject(mUUID);  		return;  	}  	else if ("copy" == action) @@ -1371,10 +1413,10 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryItem* itemp = model->getItem(mUUID);  		if (!itemp) return; -		LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); +		LLFolderViewItem* folder_view_itemp =   mInventoryPanel.get()->getItemByID(itemp->getParentUUID());  		if (!folder_view_itemp) return; -		folder_view_itemp->getListener()->pasteFromClipboard(); +		folder_view_itemp->getViewModelItem()->pasteFromClipboard();  		return;  	}  	else if ("paste_link" == action) @@ -1383,10 +1425,10 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryItem* itemp = model->getItem(mUUID);  		if (!itemp) return; -		LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); +		LLFolderViewItem* folder_view_itemp =   mInventoryPanel.get()->getItemByID(itemp->getParentUUID());  		if (!folder_view_itemp) return; -		folder_view_itemp->getListener()->pasteLinkFromClipboard(); +		folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard();  		return;  	}  	else if (isMarketplaceCopyAction(action)) @@ -1396,7 +1438,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryItem* itemp = model->getItem(mUUID);  		if (!itemp) return; -		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); +		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);  		copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId());  	}  } @@ -1497,26 +1539,27 @@ PermissionMask LLItemBridge::getPermissionMask() const  	return perm_mask;  } -const std::string& LLItemBridge::getDisplayName() const +void LLItemBridge::buildDisplayName() const  { -	if(mDisplayName.empty()) +	if(getItem())  	{ -		buildDisplayName(getItem(), mDisplayName); +		mDisplayName.assign(getItem()->getName());  	} -	return mDisplayName; +	else +	{ +		mDisplayName.assign(LLStringUtil::null);  } -void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) +	mSearchableName.assign(mDisplayName); +	mSearchableName.append(getLabelSuffix()); +	LLStringUtil::toUpper(mSearchableName); + +    //Name set, so trigger a sort +    if(mParent)  { -	if(item) -	{ -		name.assign(item->getName()); +        mParent->requestSort();  	} -	else -	{ -		name.assign(LLStringUtil::null);  	} -}  LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const  { @@ -1632,18 +1675,17 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)  	{  		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);  		new_item->rename(new_name); -		buildDisplayName(new_item, mDisplayName);  		new_item->updateServer(FALSE);  		model->updateItem(new_item);  		model->notifyObservers(); +		buildDisplayName();  	}  	// return FALSE because we either notified observers (& therefore  	// rebuilt) or we didn't update.  	return FALSE;  } -  BOOL LLItemBridge::removeItem()  {  	if(!isItemRemovable()) @@ -1651,7 +1693,6 @@ BOOL LLItemBridge::removeItem()  		return FALSE;  	} -	  	// move it to the trash  	LLPreview::hide(mUUID, TRUE);  	LLInventoryModel* model = getInventoryModel(); @@ -1789,6 +1830,99 @@ void LLFolderBridge::selectItem()  	LLInventoryModelBackgroundFetch::instance().start(getUUID(), true);  } +void LLFolderBridge::buildDisplayName() const +{ +	LLFolderType::EType preferred_type = getPreferredType(); + +	// *TODO: to be removed when database supports multi language. This is a +	// temporary attempt to display the inventory folder in the user locale. +	// mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID +	//		it uses the same way to find localized string + +	// HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) +	// Translation of Accessories folder in Library inventory folder +	bool accessories = false; +	if(getName() == "Accessories") +	{ +		//To ensure that Accessories folder is in Library we have to check its parent folder. +		//Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model +		LLInventoryCategory* cat = gInventory.getCategory(getUUID()); +		if(cat) +		{ +			const LLUUID& parent_folder_id = cat->getParentUUID(); +			accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); +		} +	} + +	//"Accessories" inventory category has folder type FT_NONE. So, this folder +	//can not be detected as protected with LLFolderType::lookupIsProtectedType +	mDisplayName.assign(getName()); +	if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) +	{ +		LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); +	} + +	mSearchableName.assign(mDisplayName); +	mSearchableName.append(getLabelSuffix()); +	LLStringUtil::toUpper(mSearchableName); + +    //Name set, so trigger a sort +    if(mParent) +    { +        mParent->requestSort(); +    } +} + + +void LLFolderBridge::update() +{ +	bool possibly_has_children = false; +	bool up_to_date = isUpToDate(); +	if(!up_to_date && hasChildren()) // we know we have children but  haven't  fetched them (doesn't obey filter) +	{ +		possibly_has_children = true; +	} + +	bool loading = (possibly_has_children +		&& !up_to_date ); + +	if (loading != mIsLoading) +	{ +		if ( loading && !mIsLoading ) +		{ +			// Measure how long we've been in the loading state +			mTimeSinceRequestStart.reset(); +		} + +		const BOOL in_inventory = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getRootFolderID()); +		const BOOL in_library = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getLibraryRootFolderID()); + +		bool root_is_loading = false; +		if (in_inventory) +		{ +			root_is_loading =   LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); +		} +		if (in_library) +		{ +			root_is_loading =   LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); +		} +		if ((mIsLoading +				&&	mTimeSinceRequestStart.getElapsedTimeF32() >=   gSavedSettings.getF32("FolderLoadingMessageWaitTime")) +			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive() +				&&	root_is_loading)) +		{ +			mDisplayName = LLInvFVBridge::getDisplayName() + " ( " +   LLTrans::getString("LoadingData") + " ) "; +			mIsLoading = true; +		} +		else +		{ +			mDisplayName = LLInvFVBridge::getDisplayName(); +			mIsLoading = false; +		} +	} +} + +  // Iterate through a folder's children to determine if  // all the children are removable.  class LLIsItemRemovable : public LLFolderViewFunctor @@ -1797,11 +1931,11 @@ public:  	LLIsItemRemovable() : mPassed(TRUE) {}  	virtual void doFolder(LLFolderViewFolder* folder)  	{ -		mPassed &= folder->getListener()->isItemRemovable(); +		mPassed &= folder->getViewModelItem()->isItemRemovable();  	}  	virtual void doItem(LLFolderViewItem* item)  	{ -		mPassed &= item->getListener()->isItemRemovable(); +		mPassed &= item->getViewModelItem()->isItemRemovable();  	}  	BOOL mPassed;  }; @@ -1815,7 +1949,7 @@ BOOL LLFolderBridge::isItemRemovable() const  	}  	LLInventoryPanel* panel = mInventoryPanel.get(); -	LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); +	LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ?   panel->getItemByID(mUUID) : NULL);  	if (folderp)  	{  		LLIsItemRemovable folder_test; @@ -2054,7 +2188,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  	LLInventoryPanel* destination_panel = mInventoryPanel.get();  	if (!destination_panel) return false; -	LLInventoryFilter* filter = destination_panel->getFilter(); +	LLInventoryFilter* filter = getInventoryFilter();  	if (!filter) return false;  	const LLUUID &cat_id = inv_cat->getUUID(); @@ -2273,7 +2407,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  				{  					// Check whether the folder being dragged from active inventory panel  					// passes the filter of the destination panel. -					is_movable = check_category(model, cat_id, active_folder_view, filter); +					is_movable = check_category(model, cat_id, active_panel, filter);  				}  			}  		} @@ -2347,7 +2481,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  			}  			else  			{ -				if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) +				if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false)))  				{  					set_dad_inbox_object(cat_id);  				} @@ -2699,7 +2833,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)  {  	if ("open" == action)  	{ -		LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mRoot->getItemByID(mUUID)); +		LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder   *>(mInventoryPanel.get()->getItemByID(mUUID));  		if (f)  		{  			f->setOpen(TRUE); @@ -2746,10 +2880,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)  	else if ("cut" == action)  	{  		cutToClipboard(); -		// MAINT-1197: This is temp code to work around a deselection/reselection bug. Please discard when merging CHUI. -		LLFolderViewItem* item_to_select = mRoot->getNextUnselectedItem(); -		LLFolderView::removeCutItems(); -		mRoot->setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, false); +		gInventory.removeObject(mUUID);  		return;  	}  	else if ("copy" == action) @@ -2790,7 +2921,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryCategory * cat = gInventory.getCategory(mUUID);  		if (!cat) return; -		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); +		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);  		copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId());  	}  #if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU @@ -2886,17 +3017,24 @@ LLUIImagePtr LLFolderBridge::getIcon() const  LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)  {  	return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); -		/*case LLAssetType::AT_MESH: -			control = "inv_folder_mesh.tga"; -			break;*/  } -LLUIImagePtr LLFolderBridge::getOpenIcon() const +LLUIImagePtr LLFolderBridge::getIconOpen() const  {  	return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE));  } +LLUIImagePtr LLFolderBridge::getIconOverlay() const +{ +	if (getInventoryObject() && getInventoryObject()->getIsLinkType()) +	{ +		return LLUI::getUIImage("Inv_Link"); +	} +	return NULL; +} + +  BOOL LLFolderBridge::renameItem(const std::string& new_name)  {  	rename_category(getInventoryModel(), mUUID, new_name); @@ -2960,6 +3098,19 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re  	return FALSE;  } +//Recursively update the folder's creation date +void LLFolderBridge::updateHierarchyCreationDate(time_t date) +{ +    if(getCreationDate() < date) +    { +        setCreationDate(date); +        if(mParent) +        { +            static_cast<LLFolderBridge *>(mParent)->updateHierarchyCreationDate(date); +        } +    } +} +  void LLFolderBridge::pasteFromClipboard()  {  	LLInventoryModel* model = getInventoryModel(); @@ -2977,7 +3128,7 @@ void LLFolderBridge::pasteFromClipboard()  		if (move_is_into_outbox)  		{ -			LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID); +			LLFolderViewItem * outbox_itemp =   mInventoryPanel.get()->getItemByID(mUUID);  			if (outbox_itemp)  			{ @@ -3000,7 +3151,7 @@ void LLFolderBridge::pasteFromClipboard()  						void * cargo_data = (void *) item;  						std::string tooltip_msg; -						can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); +						can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);  					}  				} @@ -3172,7 +3323,7 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv  	return ((item_array.count() > 0) ? TRUE : FALSE );  } -void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) +void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items, menuentry_vec_t& disabled_items)  {  	LLInventoryModel* model = getInventoryModel();  	llassert(model != NULL); @@ -3183,30 +3334,30 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)  	if (lost_and_found_id == mUUID)  	{  		// This is the lost+found folder. -		mItems.push_back(std::string("Empty Lost And Found")); +		items.push_back(std::string("Empty Lost And Found")); -		mDisabledItems.push_back(std::string("New Folder")); -		mDisabledItems.push_back(std::string("New Script")); -		mDisabledItems.push_back(std::string("New Note")); -		mDisabledItems.push_back(std::string("New Gesture")); -		mDisabledItems.push_back(std::string("New Clothes")); -		mDisabledItems.push_back(std::string("New Body Parts")); +		disabled_items.push_back(std::string("New Folder")); +		disabled_items.push_back(std::string("New Script")); +		disabled_items.push_back(std::string("New Note")); +		disabled_items.push_back(std::string("New Gesture")); +		disabled_items.push_back(std::string("New Clothes")); +		disabled_items.push_back(std::string("New Body Parts"));  	}  	if(trash_id == mUUID)  	{  		// This is the trash. -		mItems.push_back(std::string("Empty Trash")); +		items.push_back(std::string("Empty Trash"));  	}  	else if(isItemInTrash())  	{  		// This is a folder in the trash. -		mItems.clear(); // clear any items that used to exist -		addTrashContextMenuOptions(mItems, mDisabledItems); +		items.clear(); // clear any items that used to exist +		addTrashContextMenuOptions(items, disabled_items);  	}  	else if(isOutboxFolder())  	{ -		addOutboxContextMenuOptions(flags, mItems, mDisabledItems); +		addOutboxContextMenuOptions(flags, items, disabled_items);  	}  	else if(isAgentInventory()) // do not allow creating in library  	{ @@ -3220,40 +3371,40 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)  				// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.  				if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))  				{ -					mItems.push_back(std::string("New Folder")); +					items.push_back(std::string("New Folder"));  				} -				mItems.push_back(std::string("New Script")); -				mItems.push_back(std::string("New Note")); -				mItems.push_back(std::string("New Gesture")); -				mItems.push_back(std::string("New Clothes")); -				mItems.push_back(std::string("New Body Parts")); +				items.push_back(std::string("New Script")); +				items.push_back(std::string("New Note")); +				items.push_back(std::string("New Gesture")); +				items.push_back(std::string("New Clothes")); +				items.push_back(std::string("New Body Parts"));  			}  #if SUPPORT_ENSEMBLES  			// Changing folder types is an unfinished unsupported feature  			// and can lead to unexpected behavior if enabled. -			mItems.push_back(std::string("Change Type")); +			items.push_back(std::string("Change Type"));  			const LLViewerInventoryCategory *cat = getCategory();  			if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))  			{ -				mDisabledItems.push_back(std::string("Change Type")); +				disabled_items.push_back(std::string("Change Type"));  			}  #endif -			getClipboardEntries(false, mItems, mDisabledItems, flags); +			getClipboardEntries(false, items, disabled_items, flags);  		}  		else  		{  			// Want some but not all of the items from getClipboardEntries for outfits.  			if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT))  			{ -				mItems.push_back(std::string("Rename")); +				items.push_back(std::string("Rename")); -				addDeleteContextMenuOptions(mItems, mDisabledItems); +				addDeleteContextMenuOptions(items, disabled_items);  				// EXT-4030: disallow deletion of currently worn outfit  				const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();  				if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory()))  				{ -					mDisabledItems.push_back(std::string("Delete")); +					disabled_items.push_back(std::string("Delete"));  				}  			}  		} @@ -3282,20 +3433,44 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)  	// Preemptively disable system folder removal if more than one item selected.  	if ((flags & FIRST_SELECTED_ITEM) == 0)  	{ -		mDisabledItems.push_back(std::string("Delete System Folder")); +		disabled_items.push_back(std::string("Delete System Folder"));  	}  	if (!isOutboxFolder())  	{ -		mItems.push_back(std::string("Share")); +		items.push_back(std::string("Share"));  		if (!canShare())  		{ -			mDisabledItems.push_back(std::string("Share")); +			disabled_items.push_back(std::string("Share"));  		}  	} +	// Add menu items that are dependent on the contents of the folder. +	LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); +	if (category) +	{ +		uuid_vec_t folders; +		folders.push_back(category->getUUID()); + +		sSelf = getHandle(); +		LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); +		fetch->startFetch(); +		if (fetch->isFinished()) +		{ +			// Do not call execute() or done() here as if the folder is here, there's likely no point drilling down  +			// This saves lots of time as buildContextMenu() is called a lot +			delete fetch; +			buildContextMenuFolderOptions(flags, items, disabled_items); +		} +		else +		{ +			// it's all on its way - add an observer, and the inventory will call done for us when everything is here. +			inc_busy_count(); +			gInventory.addObserver(fetch); +	} +}  } -void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) +void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t& items, menuentry_vec_t& disabled_items)  {  	// Build folder specific options back up  	LLInventoryModel* model = getInventoryModel(); @@ -3322,21 +3497,21 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)  		LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);  		if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))  		{ -			mItems.push_back(std::string("Calling Card Separator")); -			mItems.push_back(std::string("Conference Chat Folder")); -			mItems.push_back(std::string("IM All Contacts In Folder")); +			items.push_back(std::string("Calling Card Separator")); +			items.push_back(std::string("Conference Chat Folder")); +			items.push_back(std::string("IM All Contacts In Folder"));  		}  	}  	if (!isItemRemovable())  	{ -		mDisabledItems.push_back(std::string("Delete")); +		disabled_items.push_back(std::string("Delete"));  	}  #ifndef LL_RELEASE_FOR_DOWNLOAD  	if (LLFolderType::lookupIsProtectedType(type))  	{ -		mItems.push_back(std::string("Delete System Folder")); +		items.push_back(std::string("Delete System Folder"));  	}  #endif @@ -3351,7 +3526,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)  		checkFolderForContentsOfType(model, is_object) ||  		checkFolderForContentsOfType(model, is_gesture) )  	{ -		mItems.push_back(std::string("Folder Wearables Separator")); +		items.push_back(std::string("Folder Wearables Separator"));  		// Only enable add/replace outfit for non-system folders.  		if (!is_system_folder) @@ -3359,25 +3534,25 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)  			// Adding an outfit onto another (versus replacing) doesn't make sense.  			if (type != LLFolderType::FT_OUTFIT)  			{ -				mItems.push_back(std::string("Add To Outfit")); +				items.push_back(std::string("Add To Outfit"));  			} -			mItems.push_back(std::string("Replace Outfit")); +			items.push_back(std::string("Replace Outfit"));  		}  		if (is_ensemble)  		{ -			mItems.push_back(std::string("Wear As Ensemble")); +			items.push_back(std::string("Wear As Ensemble"));  		} -		mItems.push_back(std::string("Remove From Outfit")); +		items.push_back(std::string("Remove From Outfit"));  		if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))  		{ -			mDisabledItems.push_back(std::string("Remove From Outfit")); +			disabled_items.push_back(std::string("Remove From Outfit"));  		}  		if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))  		{ -			mDisabledItems.push_back(std::string("Replace Outfit")); +			disabled_items.push_back(std::string("Replace Outfit"));  		} -		mItems.push_back(std::string("Outfit Separator")); +		items.push_back(std::string("Outfit Separator"));  	}  } @@ -3386,49 +3561,28 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  {  	sSelf.markDead(); -	mItems.clear(); -	mDisabledItems.clear(); +	// fetch contents of this folder, as context menu can depend on contents +	// still, user would have to open context menu again to see the changes +	gInventory.fetchDescendentsOf(getUUID()); + + +	menuentry_vec_t items; +	menuentry_vec_t disabled_items;  	lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;  	LLInventoryModel* model = getInventoryModel();  	if(!model) return; -	buildContextMenuBaseOptions(flags); - -	// Add menu items that are dependent on the contents of the folder. -	LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); -	if (category) -	{ -		uuid_vec_t folders; -		folders.push_back(category->getUUID()); - -		sSelf = getHandle(); -		LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); -		fetch->startFetch(); -		if (fetch->isFinished()) -		{ -			// Do not call execute() or done() here as if the folder is here, there's likely no point drilling down  -			// This saves lots of time as buildContextMenu() is called a lot -			delete fetch; -			buildContextMenuFolderOptions(flags); -		} -		else -		{ -			// it's all on its way - add an observer, and the inventory will call done for us when everything is here. -			inc_busy_count(); -			gInventory.addObserver(fetch); -		} -	} - -	hide_context_entries(menu, mItems, mDisabledItems); +	buildContextMenuOptions(flags, items, disabled_items); +        hide_context_entries(menu, items, disabled_items);  	// Reposition the menu, in case we're adding items to an existing menu.  	menu.needsArrange();  	menu.arrangeAndClear();  } -BOOL LLFolderBridge::hasChildren() const +bool LLFolderBridge::hasChildren() const  {  	LLInventoryModel* model = getInventoryModel();  	if(!model) return FALSE; @@ -3518,25 +3672,6 @@ void LLFolderBridge::pasteClipboard(void* user_data)  	if(self) self->pasteFromClipboard();  } -void LLFolderBridge::createNewCategory(void* user_data) -{ -	LLFolderBridge* bridge = (LLFolderBridge*)user_data; -	if(!bridge) return; -	LLInventoryPanel* panel = bridge->mInventoryPanel.get(); -	if (!panel) return; -	LLInventoryModel* model = panel->getModel(); -	if(!model) return; -	LLUUID id; -	id = model->createNewCategory(bridge->getUUID(), -								  LLFolderType::FT_NONE, -								  LLStringUtil::null); -	model->notifyObservers(); - -	// At this point, the bridge has probably been deleted, but the -	// view is still there. -	panel->setSelection(id, TAKE_FOCUS_YES); -} -  void LLFolderBridge::createNewShirt(void* user_data)  {  	LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHIRT); @@ -3602,6 +3737,24 @@ void LLFolderBridge::createNewEyes(void* user_data)  	LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_EYES);  } +EInventorySortGroup LLFolderBridge::getSortGroup() const +{ +	LLFolderType::EType preferred_type = getPreferredType(); + +	if (preferred_type == LLFolderType::FT_TRASH) +	{ +		return SG_TRASH_FOLDER; +	} + +	if(LLFolderType::lookupIsProtectedType(preferred_type)) +	{ +		return SG_SYSTEM_FOLDER; +	} + +	return SG_NORMAL_FOLDER; +} + +  // static  void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::EType type)  { @@ -3704,9 +3857,10 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)  	LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback();  	LLInventoryPanel* panel = mInventoryPanel.get();  	LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; -	if (drag_over_item && drag_over_item->getListener()) +	LLFolderViewModelItemInventory* view_model = drag_over_item ? static_cast<LLFolderViewModelItemInventory*>(drag_over_item->getViewModelItem()) : NULL; +	if (view_model)  	{ -		cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); +		cb.get()->setTargetLandmarkId(view_model->getUUID());  	}  	copy_inventory_item( @@ -3755,7 +3909,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  	LLInventoryPanel* destination_panel = mInventoryPanel.get();  	if (!destination_panel) return false; -	LLInventoryFilter* filter = destination_panel->getFilter(); +	LLInventoryFilter* filter = getInventoryFilter();  	if (!filter) return false;  	const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); @@ -3872,13 +4026,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  		// passes the filter of the destination panel.  		if (accept && active_panel)  		{ -			LLFolderView* active_folder_view = active_panel->getRootFolder(); -			if (!active_folder_view) return false; - -			LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); +			LLFolderViewItem* fv_item =   active_panel->getItemByID(inv_item->getUUID());  			if (!fv_item) return false; -			accept = filter->check(fv_item); +			accept = filter->check(fv_item->getViewModelItem());  		}  		if (accept && drop) @@ -3890,6 +4041,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			}  			// If an item is being dragged between windows, unselect everything in the active window   			// so that we don't follow the selection to its new location (which is very annoying). +                        // RN: a better solution would be to deselect automatically when an   item is moved +			// and then select any item that is dropped only in the panel that it   is dropped in  			if (active_panel && (destination_panel != active_panel))  				{  					active_panel->unSelectAll(); @@ -3907,8 +4060,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  				if (itemp)  				{  					LLUUID srcItemId = inv_item->getUUID(); -					LLUUID destItemId = itemp->getListener()->getUUID(); -					gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); +					LLUUID destItemId = static_cast<LLFolderViewModelItemInventory*>(itemp->getViewModelItem())->getUUID(); +					LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(srcItemId, destItemId);  				}  			} @@ -3940,7 +4093,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			else  			{  				// set up observer to select item once drag and drop from inbox is complete  -				if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) +				if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false)))  				{  					set_dad_inbox_object(inv_item->getUUID());  				} @@ -4095,13 +4248,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			// passes the filter of the destination panel.  			if (accept && active_panel)  			{ -				LLFolderView* active_folder_view = active_panel->getRootFolder(); -				if (!active_folder_view) return false; - -				LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); +				LLFolderViewItem* fv_item =   active_panel->getItemByID(inv_item->getUUID());  				if (!fv_item) return false; -				accept = filter->check(fv_item); +				accept = filter->check(fv_item->getViewModelItem());  			}  			if (accept && drop) @@ -4141,10 +4291,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  // static  bool check_category(LLInventoryModel* model,  					const LLUUID& cat_id, -					LLFolderView* active_folder_view, +					LLInventoryPanel* active_panel,  					LLInventoryFilter* filter)  { -	if (!model || !active_folder_view || !filter) +	if (!model || !active_panel || !filter)  		return false;  	if (!filter->checkFolder(cat_id)) @@ -4164,13 +4314,13 @@ bool check_category(LLInventoryModel* model,  		// Empty folder should be checked as any other folder view item.  		// If we are filtering by date the folder should not pass because  		// it doesn't have its own creation date. See LLInvFVBridge::getCreationDate(). -		return check_item(cat_id, active_folder_view, filter); +		return check_item(cat_id, active_panel, filter);  	}  	for (S32 i = 0; i < num_descendent_categories; ++i)  	{  		LLInventoryCategory* category = descendent_categories[i]; -		if(!check_category(model, category->getUUID(), active_folder_view, filter)) +		if(!check_category(model, category->getUUID(), active_panel, filter))  		{  			return false;  		} @@ -4179,7 +4329,7 @@ bool check_category(LLInventoryModel* model,  	for (S32 i = 0; i < num_descendent_items; ++i)  	{  		LLViewerInventoryItem* item = descendent_items[i]; -		if(!check_item(item->getUUID(), active_folder_view, filter)) +		if(!check_item(item->getUUID(), active_panel, filter))  		{  			return false;  		} @@ -4190,15 +4340,15 @@ bool check_category(LLInventoryModel* model,  // static  bool check_item(const LLUUID& item_id, -				LLFolderView* active_folder_view, +				LLInventoryPanel* active_panel,  				LLInventoryFilter* filter)  { -	if (!active_folder_view || !filter) return false; +	if (!active_panel || !filter) return false; -	LLFolderViewItem* fv_item = active_folder_view->getItemByID(item_id); +	LLFolderViewItem* fv_item = active_panel->getItemByID(item_id);  	if (!fv_item) return false; -	return filter->check(fv_item); +	return filter->check(fv_item->getViewModelItem());  }  // +=================================================+ @@ -4300,15 +4450,6 @@ void LLSoundBridge::openItem()  	}  } -void LLSoundBridge::previewItem() -{ -	LLViewerInventoryItem* item = getItem(); -	if(item) -	{ -		send_sound_trigger(item->getAssetUUID(), 1.0); -	} -} -  void LLSoundBridge::openSoundPreview(void* which)  {  	LLSoundBridge *me = (LLSoundBridge *)which; @@ -4524,7 +4665,7 @@ LLCallingCardBridge::~LLCallingCardBridge()  void LLCallingCardBridge::refreshFolderViewItem()  {  	LLInventoryPanel* panel = mInventoryPanel.get(); -	LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; +	LLFolderViewItem* itemp = panel ? panel->getItemByID(mUUID) : NULL;  	if (itemp)  	{  		itemp->refresh(); @@ -5315,11 +5456,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)  	{  		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);  		new_item->rename(new_name); -		buildDisplayName(new_item, mDisplayName);  		new_item->updateServer(FALSE);  		model->updateItem(new_item); -  		model->notifyObservers(); +		buildDisplayName();  		if (isAgentAvatarValid())  		{ @@ -5919,16 +6059,6 @@ void LLMeshBridge::openItem()  	}  } -void LLMeshBridge::previewItem() -{ -	LLViewerInventoryItem* item = getItem(); -	if(item) -	{ -		// preview mesh -	} -} - -  void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  {  	lldebugs << "LLMeshBridge::buildContextMenu()" << llendl; @@ -6017,14 +6147,15 @@ void LLLinkFolderBridge::gotoItem()  	const LLUUID &cat_uuid = getFolderID();  	if (!cat_uuid.isNull())  	{ -		if (LLFolderViewItem *base_folder = mRoot->getItemByID(cat_uuid)) +		LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid); +		if (base_folder)  		{  			if (LLInventoryModel* model = getInventoryModel())  			{  				model->fetchDescendentsOf(cat_uuid);  			}  			base_folder->setOpen(TRUE); -			mRoot->setSelectionFromRoot(base_folder,TRUE); +			mRoot->setSelection(base_folder,TRUE);  			mRoot->scrollToShowSelection();  		}  	} @@ -6355,9 +6486,8 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_  /************************************************************************/  void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  { -	LLFolderBridge::buildContextMenu(menu, flags); - -	menuentry_vec_t disabled_items, items = getMenuItems(); +	menuentry_vec_t disabled_items, items; +        buildContextMenuOptions(flags, items, disabled_items);  	items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); @@ -6369,42 +6499,29 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(  	LLAssetType::EType actual_asset_type,  	LLInventoryType::EType inv_type,  	LLInventoryPanel* inventory, +	LLFolderViewModelInventory* view_model,  	LLFolderView* root,  	const LLUUID& uuid,  	U32 flags /*= 0x00*/ ) const  {  	LLInvFVBridge* new_listener = NULL; -	switch(asset_type) +	if (asset_type == LLAssetType::AT_CATEGORY  +		&& actual_asset_type != LLAssetType::AT_LINK_FOLDER)  	{ -	case LLAssetType::AT_CATEGORY: -		if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) +		new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); +	} +	else  		{ -			// *TODO: Create a link folder handler instead if it is necessary -			new_listener = LLInventoryFVBridgeBuilder::createBridge( -				asset_type, +		new_listener = LLInventoryFolderViewModelBuilder::createBridge(asset_type,  				actual_asset_type,  				inv_type,  				inventory, +																view_model,  				root,  				uuid,  				flags); -			break;  		} -		new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); -		break; -	default: -		new_listener = LLInventoryFVBridgeBuilder::createBridge( -			asset_type, -			actual_asset_type, -			inv_type, -			inventory, -			root, -			uuid, -			flags); -	}  	return new_listener; -  } -  // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index dc9e88d54d..6beccf19ae 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -29,11 +29,13 @@  #include "llcallingcard.h"  #include "llfloaterproperties.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "llinventorymodel.h"  #include "llinventoryobserver.h" +#include "llinventorypanel.h"  #include "llviewercontrol.h"  #include "llwearable.h" +#include "lltooldraganddrop.h"  class LLInventoryFilter;  class LLInventoryPanel; @@ -41,7 +43,7 @@ class LLInventoryModel;  class LLMenuGL;  class LLCallingCardObserver;  class LLViewerJointAttachment; - +class LLFolderView;  typedef std::vector<std::string> menuentry_vec_t; @@ -56,7 +58,7 @@ typedef std::vector<std::string> menuentry_vec_t;  // functionality a bit. (except for folders, you can create those  // manually...)  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInvFVBridge : public LLFolderViewEventListener +class LLInvFVBridge : public LLFolderViewModelItemInventory  {  public:  	// This method is a convenience function which creates the correct @@ -65,6 +67,7 @@ public:  									   LLAssetType::EType actual_asset_type,  									   LLInventoryType::EType inv_type,  									   LLInventoryPanel* inventory, +									   LLFolderViewModelInventory* view_model,  									   LLFolderView* root,  									   const LLUUID& uuid,  									   U32 flags = 0x00); @@ -78,23 +81,25 @@ public:  	// LLInvFVBridge functionality  	//--------------------------------------------------------------------  	virtual const LLUUID& getUUID() const { return mUUID; } -	virtual void clearDisplayName() {} +	virtual void clearDisplayName() { mDisplayName.clear(); }  	virtual void restoreItem() {}  	virtual void restoreToWorld() {}  	//-------------------------------------------------------------------- -	// Inherited LLFolderViewEventListener functions +	// Inherited LLFolderViewModelItemInventory functions  	//--------------------------------------------------------------------  	virtual const std::string& getName() const;  	virtual const std::string& getDisplayName() const; +	const std::string& getSearchableName() const { return mSearchableName; } +  	virtual PermissionMask getPermissionMask() const;  	virtual LLFolderType::EType getPreferredType() const;  	virtual time_t getCreationDate() const; +        virtual void setCreationDate(time_t creation_date_utc);  	virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }  	virtual std::string getLabelSuffix() const { return LLStringUtil::null; }  	virtual void openItem() {}  	virtual void closeItem() {} -	virtual void previewItem() {openItem();}  	virtual void showProperties();  	virtual BOOL isItemRenameable() const { return TRUE; }  	//virtual BOOL renameItem(const std::string& new_name) {} @@ -103,8 +108,8 @@ public:  	virtual BOOL isItemInTrash() const;  	virtual BOOL isLink() const;  	//virtual BOOL removeItem() = 0; -	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); -	virtual void move(LLFolderViewEventListener* new_parent_bridge) {} +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); +	virtual void move(LLFolderViewModelItem* new_parent_bridge) {}  	virtual BOOL isItemCopyable() const { return FALSE; }  	virtual BOOL copyToClipboard() const;  	virtual BOOL cutToClipboard() const; @@ -115,6 +120,7 @@ public:  	void getClipboardEntries(bool show_asset_id, menuentry_vec_t &items,   							 menuentry_vec_t &disabled_items, U32 flags);  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags); +    virtual LLToolDragAndDrop::ESource getDragSource() const;  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type, @@ -122,6 +128,9 @@ public:  							std::string& tooltip_msg) { return FALSE; }  	virtual LLInventoryType::EType getInventoryType() const { return mInvType; }  	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } +        EInventorySortGroup getSortGroup()  const { return SG_ITEM; } +	virtual LLInventoryObject* getInventoryObject() const; +  	//--------------------------------------------------------------------  	// Convenience functions for adding various common menu options. @@ -138,16 +147,16 @@ protected:  protected:  	LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); -	LLInventoryObject* getInventoryObject() const;  	LLInventoryModel* getInventoryModel() const; +	LLInventoryFilter* getInventoryFilter() const;  	BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?  	BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory?  	BOOL isAgentInventory() const; // false if lost or in the inventory library -	BOOL isCOFFolder() const; // true if COF or descendent of -	BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox -	BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox +	BOOL isCOFFolder() const;       // true if COF or descendant of +	BOOL isInboxFolder() const;     // true if COF or descendant of   marketplace inbox +	BOOL isOutboxFolder() const;    // true if COF or descendant of   marketplace outbox  	BOOL isOutboxFolderDirectParent() const;  	const LLUUID getOutboxFolder() const; @@ -160,30 +169,36 @@ protected:  									 LLViewerInventoryCategory* item,  									 const LLUUID& new_parent,  									 BOOL restamp); -	void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch); +	void removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch);  protected: -	LLHandle<LLInventoryPanel> mInventoryPanel; -	LLFolderView* mRoot; -	const LLUUID mUUID;	// item id -	LLInventoryType::EType mInvType; -	BOOL mIsLink; +	LLHandle<LLInventoryPanel>	mInventoryPanel; +	LLFolderView*				mRoot; +	const LLUUID				mUUID;	// item id +	LLInventoryType::EType		mInvType; +	bool						mIsLink; +	LLTimer						mTimeSinceRequestStart; +	mutable std::string			mDisplayName; +	mutable std::string			mSearchableName; +  	void purgeItem(LLInventoryModel *model, const LLUUID &uuid); +	virtual void buildDisplayName() const {}  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInvFVBridgeBuilder +// Class LLInventoryFolderViewModelBuilder  // -// This class intended to build Folder View Bridge via LLInvFVBridge::createBridge. -// It can be overridden with another way of creation necessary Inventory-Folder-View-Bridge. +// This class intended to build Folder View Model via LLInvFVBridge::createBridge. +// It can be overridden with another way of creation necessary Inventory Folder View Models.  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryFVBridgeBuilder +class LLInventoryFolderViewModelBuilder  {  public: - 	virtual ~LLInventoryFVBridgeBuilder() {} + 	virtual ~LLInventoryFolderViewModelBuilder() {}  	virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type,  										LLAssetType::EType actual_asset_type,  										LLInventoryType::EType inv_type,  										LLInventoryPanel* inventory, +										LLFolderViewModelInventory* view_model,  										LLFolderView* root,  										const LLUUID& uuid,  										U32 flags = 0x00) const; @@ -203,7 +218,6 @@ public:  	virtual void restoreToWorld();  	virtual void gotoItem();  	virtual LLUIImagePtr getIcon() const; -	virtual const std::string& getDisplayName() const;  	virtual std::string getLabelSuffix() const;  	virtual LLFontGL::StyleFlags getLabelStyle() const;  	virtual PermissionMask getPermissionMask() const; @@ -212,19 +226,16 @@ public:  	virtual BOOL renameItem(const std::string& new_name);  	virtual BOOL removeItem();  	virtual BOOL isItemCopyable() const; -	virtual BOOL hasChildren() const { return FALSE; } +	virtual bool hasChildren() const { return FALSE; }  	virtual BOOL isUpToDate() const { return TRUE; } -	/*virtual*/ void clearDisplayName() { mDisplayName.clear(); } -  	LLViewerInventoryItem* getItem() const;  protected:  	BOOL confirmRemoveItem(const LLSD& notification, const LLSD& response);  	virtual BOOL isItemPermissive() const; -	static void buildDisplayName(LLInventoryItem* item, std::string& name); +	virtual void buildDisplayName() const; -	mutable std::string mDisplayName;  };  class LLFolderBridge : public LLInvFVBridge @@ -232,15 +243,18 @@ class LLFolderBridge : public LLInvFVBridge  public:  	LLFolderBridge(LLInventoryPanel* inventory,   				   LLFolderView* root, -				   const LLUUID& uuid) : -		LLInvFVBridge(inventory, root, uuid), +				   const LLUUID& uuid)  +        :       LLInvFVBridge(inventory, root, uuid),  		mCallingCards(FALSE), -		mWearables(FALSE) +		mWearables(FALSE), +		mIsLoading(false)  	{}  	BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg);  	BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); +    virtual void buildDisplayName() const; +  	virtual void performAction(LLInventoryModel* model, std::string action);  	virtual void openItem();  	virtual void closeItem(); @@ -250,7 +264,9 @@ public:  	virtual LLFolderType::EType getPreferredType() const;  	virtual LLUIImagePtr getIcon() const; -	virtual LLUIImagePtr getOpenIcon() const; +	virtual LLUIImagePtr getIconOpen() const; +	virtual LLUIImagePtr getIconOverlay() const; +  	static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);  	virtual BOOL renameItem(const std::string& new_name); @@ -258,11 +274,12 @@ public:  	virtual BOOL removeItem();  	BOOL removeSystemFolder();  	bool removeItemResponse(const LLSD& notification, const LLSD& response); +    void updateHierarchyCreationDate(time_t date);  	virtual void pasteFromClipboard();  	virtual void pasteLinkFromClipboard();  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags); -	virtual BOOL hasChildren() const; +	virtual bool hasChildren() const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type,  							void* cargo_data, @@ -275,20 +292,24 @@ public:  	virtual BOOL isClipboardPasteable() const;  	virtual BOOL isClipboardPasteableAsLink() const; +	EInventorySortGroup getSortGroup()  const; +	virtual void update(); +  	static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type);  	LLViewerInventoryCategory* getCategory() const;  	LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; } +	bool isLoading() { return mIsLoading; } +  protected: -	void buildContextMenuBaseOptions(U32 flags); -	void buildContextMenuFolderOptions(U32 flags); +	void buildContextMenuOptions(U32 flags, menuentry_vec_t& items,   menuentry_vec_t& disabled_items); +	void buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items,   menuentry_vec_t& disabled_items);  	//--------------------------------------------------------------------  	// Menu callbacks  	//--------------------------------------------------------------------  	static void pasteClipboard(void* user_data); -	static void createNewCategory(void* user_data);  	static void createNewShirt(void* user_data);  	static void createNewPants(void* user_data);  	static void createNewShoes(void* user_data); @@ -308,8 +329,6 @@ protected:  	void modifyOutfit(BOOL append);  	void determineFolderType(); -	menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items -  	void dropToFavorites(LLInventoryItem* inv_item);  	void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); @@ -321,11 +340,12 @@ public:  	static void staticFolderOptionsMenu();  private: -	BOOL				mCallingCards; -	BOOL				mWearables; -	menuentry_vec_t		mItems; -	menuentry_vec_t		mDisabledItems; -	LLRootHandle<LLFolderBridge> mHandle; + +	bool							mCallingCards; +	bool							mWearables; +	bool							mIsLoading; +	LLTimer							mTimeSinceRequestStart; +	LLRootHandle<LLFolderBridge>	mHandle;  };  class LLTextureBridge : public LLItemBridge @@ -354,7 +374,6 @@ public:  				  const LLUUID& uuid) :  		LLItemBridge(inventory, root, uuid) {}  	virtual void openItem(); -	virtual void previewItem();  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  	static void openSoundPreview(void*);  }; @@ -544,7 +563,6 @@ class LLMeshBridge : public LLItemBridge  public:  	virtual LLUIImagePtr getIcon() const;  	virtual void openItem(); -	virtual void previewItem();  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  protected: @@ -620,7 +638,7 @@ public:  };  // Bridge builder to create Inventory-Folder-View-Bridge for Recent Inventory Panel -class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder +class LLRecentInventoryBridgeBuilder : public LLInventoryFolderViewModelBuilder  {  public:  	// Overrides FolderBridge for Recent Inventory Panel. @@ -629,6 +647,7 @@ public:  		LLAssetType::EType actual_asset_type,  		LLInventoryType::EType inv_type,  		LLInventoryPanel* inventory, +		LLFolderViewModelInventory* view_model,  		LLFolderView* root,  		const LLUUID& uuid,  		U32 flags = 0x00) const; diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 4573074c73..c913269aad 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -29,7 +29,7 @@  #include "llinventoryfilter.h"  // viewer includes -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "llfolderviewitem.h"  #include "llinventorymodel.h"  #include "llinventorymodelbackgroundfetch.h" @@ -42,109 +42,90 @@  #include "llclipboard.h"  #include "lltrans.h" +//TODO RN: fix use of static cast as much as possible +  LLFastTimer::DeclareTimer FT_FILTER_CLIPBOARD("Filter Clipboard"); -LLInventoryFilter::FilterOps::FilterOps() : -	mFilterObjectTypes(0xffffffffffffffffULL), -	mFilterCategoryTypes(0xffffffffffffffffULL), -	mFilterWearableTypes(0xffffffffffffffffULL), -	mMinDate(time_min()), -	mMaxDate(time_max()), -	mHoursAgo(0), -	mShowFolderState(SHOW_NON_EMPTY_FOLDERS), -	mPermissions(PERM_NONE), -	mFilterTypes(FILTERTYPE_OBJECT), -	mFilterUUID(LLUUID::null), -	mFilterLinks(FILTERLINK_INCLUDE_LINKS) +LLInventoryFilter::FilterOps::FilterOps(const Params& p) +:	mFilterObjectTypes(p.object_types), +	mFilterCategoryTypes(p.category_types), +	mFilterWearableTypes(p.wearable_types), +	mMinDate(p.date_range.min_date), +	mMaxDate(p.date_range.max_date), +	mHoursAgo(p.hours_ago), +	mShowFolderState(p.show_folder_state), +	mPermissions(p.permissions), +	mFilterTypes(p.types), +	mFilterUUID(p.uuid), +	mFilterLinks(p.links)  {  }  ///----------------------------------------------------------------------------  /// Class LLInventoryFilter  ///---------------------------------------------------------------------------- -LLInventoryFilter::LLInventoryFilter(const std::string& name) -:	mName(name), -	mModified(FALSE), -	mNeedTextRebuild(TRUE), -	mEmptyLookupMessage("InventoryNoMatchingItems") +LLInventoryFilter::LLInventoryFilter(const Params& p) +:	mName(p.name), +	mFilterModified(FILTER_NONE), +	mEmptyLookupMessage("InventoryNoMatchingItems"), +    mFilterOps(p.filter_ops), +	mFilterSubString(p.substring), +	mCurrentGeneration(0), +	mFirstRequiredGeneration(0), +	mFirstSuccessGeneration(0), +	mFilterCount(0)  { -	mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately - -	mSubStringMatchOffset = 0; -	mFilterSubString.clear(); -	mFilterGeneration = 0; -	mMustPassGeneration = S32_MAX; -	mMinRequiredGeneration = 0; -	mFilterCount = 0; -	mNextFilterGeneration = mFilterGeneration + 1; - -	mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff"); -	mFilterBehavior = FILTER_NONE; +	mNextFilterGeneration = mCurrentGeneration + 1;  	// copy mFilterOps into mDefaultFilterOps  	markDefault();  } -LLInventoryFilter::~LLInventoryFilter() -{ -} - -BOOL LLInventoryFilter::check(const LLFolderViewItem* item)  +bool LLInventoryFilter::check(const LLFolderViewModelItem* item)   { +	const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item);  	// Clipboard cut items are *always* filtered so we need this value upfront -	const LLFolderViewEventListener* listener = item->getListener();  	const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE);  	// If it's a folder and we're showing all folders, return automatically. -	const BOOL is_folder = (dynamic_cast<const LLFolderViewFolder*>(item) != NULL); +	const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;  	if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS))  	{  		return passed_clipboard;  	} -	mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; +	std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; -	const BOOL passed_filtertype = checkAgainstFilterType(item); -	const BOOL passed_permissions = checkAgainstPermissions(item); -	const BOOL passed_filterlink = checkAgainstFilterLinks(item); -	const BOOL passed = (passed_filtertype && -						 passed_permissions && -						 passed_filterlink && -						 passed_clipboard && -						 (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); +	BOOL passed = (mFilterSubString.size() == 0 || string_offset != std::string::npos); +	passed = passed && checkAgainstFilterType(listener); +	passed = passed && checkAgainstPermissions(listener); +	passed = passed && checkAgainstFilterLinks(listener); +	passed = passed && passed_clipboard;  	return passed;  }  bool LLInventoryFilter::check(const LLInventoryItem* item)  { -	mSubStringMatchOffset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; +	std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos;  	const bool passed_filtertype = checkAgainstFilterType(item);  	const bool passed_permissions = checkAgainstPermissions(item);  	const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID()); -	const bool passed = (passed_filtertype && -						 passed_permissions && -						 passed_clipboard && -						 (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); +	const bool passed = (passed_filtertype  +		&& passed_permissions +		&& passed_clipboard  +		&&	(mFilterSubString.size() == 0 || string_offset != std::string::npos));  	return passed;  } -bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const +bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const  { -	if (!folder) -	{ -		llwarns << "The filter can not be checked on an invalid folder." << llendl; -		llassert(false); // crash in development builds -		return false; -	} - -	const LLFolderViewEventListener* listener = folder->getListener(); +	const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item);  	if (!listener)  	{ -		llwarns << "Folder view event listener not found." << llendl; -		llassert(false); // crash in development builds +		llerrs << "Folder view event listener not found." << llendl;  		return false;  	} @@ -155,6 +136,13 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const  bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const  { +	// when applying a filter, matching folders get their contents downloaded first +	if (isNotDefault() +		&& !gInventory.isCategoryComplete(folder_id)) +	{ +		LLInventoryModelBackgroundFetch::instance().start(folder_id); +	} +  	// Always check against the clipboard  	const BOOL passed_clipboard = checkAgainstClipboard(folder_id); @@ -163,14 +151,14 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const  	{  		return passed_clipboard;  	} - +	  	if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)  	{  		// Can only filter categories for items in your inventory  		// (e.g. versus in-world object contents).  		const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);  		if (!cat) -			return false; +			return folder_id.isNull();  		LLFolderType::EType cat_type = cat->getPreferredType();  		if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0))  			return false; @@ -179,9 +167,8 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const  	return passed_clipboard;  } -BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const  { -	const LLFolderViewEventListener* listener = item->getListener();  	if (!listener) return FALSE;  	LLInventoryType::EType object_type = listener->getInventoryType(); @@ -268,7 +255,7 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con  			}  		}  	} - +	  	return TRUE;  } @@ -347,13 +334,12 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const  	return true;  } -BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewModelItemInventory* listener) const  { -	const LLFolderViewEventListener* listener = item->getListener();  	if (!listener) return FALSE;  	PermissionMask perm = listener->getPermissionMask(); -	const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getListener()); +	const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(listener);  	if (bridge && bridge->isLink())  	{  		const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID()); @@ -375,9 +361,8 @@ bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) con  	return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions;  } -BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewModelItemInventory* listener) const  { -	const LLFolderViewEventListener* listener = item->getListener();  	if (!listener) return TRUE;  	const LLUUID object_id = listener->getUUID(); @@ -397,20 +382,21 @@ const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const  	return mFilterSubString;  } -std::string::size_type LLInventoryFilter::getStringMatchOffset() const +std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewModelItem* item) const  { -	return mSubStringMatchOffset; +	const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item); +	return mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos;  } -BOOL LLInventoryFilter::isDefault() const +bool LLInventoryFilter::isDefault() const  {  	return !isNotDefault();  }  // has user modified default filter params? -BOOL LLInventoryFilter::isNotDefault() const +bool LLInventoryFilter::isNotDefault() const  { -	BOOL not_default = FALSE; +	S32 not_default = 0;  	not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes);  	not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes); @@ -422,11 +408,11 @@ BOOL LLInventoryFilter::isNotDefault() const  	not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate);  	not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate);  	not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo); -	 -	return not_default; + +	return not_default != 0;  } -BOOL LLInventoryFilter::isActive() const +bool LLInventoryFilter::isActive() const  {  	return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL  		|| mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL @@ -440,16 +426,9 @@ BOOL LLInventoryFilter::isActive() const  		|| mFilterOps.mHoursAgo != 0;  } -BOOL LLInventoryFilter::isModified() const +bool LLInventoryFilter::isModified() const  { -	return mModified; -} - -BOOL LLInventoryFilter::isModifiedAndClear() -{ -	BOOL ret = mModified; -	mModified = FALSE; -	return ret; +	return mFilterModified != FILTER_NONE;  }  void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types) @@ -613,9 +592,10 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)  void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)  { +	static LLCachedControl<U32> s_last_logoff(gSavedPerAccountSettings, "LastLogoff", 0);  	if (sl && !isSinceLogoff())  	{ -		setDateRange(mLastLogoff, time_max()); +		setDateRange(s_last_logoff(), time_max());  		setModified();  	}  	if (!sl && isSinceLogoff()) @@ -634,17 +614,18 @@ void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)  	}  } -BOOL LLInventoryFilter::isSinceLogoff() const +bool LLInventoryFilter::isSinceLogoff() const  { -	return (mFilterOps.mMinDate == (time_t)mLastLogoff) && +	static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0); + +	return (mFilterOps.mMinDate == (time_t)s_last_logoff()) &&  		(mFilterOps.mMaxDate == time_max()) &&  		(mFilterOps.mFilterTypes & FILTERTYPE_DATE);  }  void LLInventoryFilter::clearModified()  { -	mModified = FALSE;  -	mFilterBehavior = FILTER_NONE; +	mFilterModified = FILTER_NONE;  }  void LLInventoryFilter::setHoursAgo(U32 hours) @@ -722,15 +703,6 @@ void LLInventoryFilter::setShowFolderState(EFolderShow state)  	}  } -void LLInventoryFilter::setSortOrder(U32 order) -{ -	if (mOrder != order) -	{ -		mOrder = order; -		setModified(); -	} -} -  void LLInventoryFilter::markDefault()  {  	mDefaultFilterOps = mFilterOps; @@ -742,83 +714,68 @@ void LLInventoryFilter::resetDefault()  	setModified();  } -void LLInventoryFilter::setModified(EFilterBehavior behavior) +void LLInventoryFilter::setModified(EFilterModified behavior)  { -	mModified = TRUE; -	mNeedTextRebuild = TRUE; -	mFilterGeneration = mNextFilterGeneration++; +	mFilterText.clear(); +	mCurrentGeneration = mNextFilterGeneration++; -	if (mFilterBehavior == FILTER_NONE) +	if (mFilterModified == FILTER_NONE)  	{ -		mFilterBehavior = behavior; +		mFilterModified = behavior;  	} -	else if (mFilterBehavior != behavior) +	else if (mFilterModified != behavior)  	{  		// trying to do both less restrictive and more restrictive filter  		// basically means restart from scratch -		mFilterBehavior = FILTER_RESTART; +		mFilterModified = FILTER_RESTART;  	} -	if (isNotDefault()) +	// if not keeping current filter results, update last valid as well +	switch(mFilterModified)  	{ -		// if not keeping current filter results, update last valid as well -		switch(mFilterBehavior) -		{ -			case FILTER_RESTART: -				mMustPassGeneration = mFilterGeneration; -				mMinRequiredGeneration = mFilterGeneration; -				break; -			case FILTER_LESS_RESTRICTIVE: -				mMustPassGeneration = mFilterGeneration; -				break; -			case FILTER_MORE_RESTRICTIVE: -				mMinRequiredGeneration = mFilterGeneration; -				// must have passed either current filter generation (meaningless, as it hasn't been run yet) -				// or some older generation, so keep the value -				mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); -				break; -			default: -				llerrs << "Bad filter behavior specified" << llendl; -		} -	} -	else -	{ -		// shortcut disabled filters to show everything immediately -		mMinRequiredGeneration = 0; -		mMustPassGeneration = S32_MAX; +		case FILTER_RESTART: +			mFirstRequiredGeneration = mCurrentGeneration; +			mFirstSuccessGeneration = mCurrentGeneration; +			break; +		case FILTER_LESS_RESTRICTIVE: +			mFirstRequiredGeneration = mCurrentGeneration; +			break; +		case FILTER_MORE_RESTRICTIVE: +			mFirstSuccessGeneration = mCurrentGeneration; +			break; +		default: +			llerrs << "Bad filter behavior specified" << llendl;  	}  } -BOOL LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const +bool LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const  {  	return mFilterOps.mFilterObjectTypes & (1LL << t);  }  const std::string& LLInventoryFilter::getFilterText()  { -	if (!mNeedTextRebuild) +	if (!mFilterText.empty())  	{  		return mFilterText;  	} -	mNeedTextRebuild = FALSE;  	std::string filtered_types;  	std::string not_filtered_types;  	BOOL filtered_by_type = FALSE;  	BOOL filtered_by_all_types = TRUE;  	S32 num_filter_types = 0; +  	mFilterText.clear();  	if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION))  	{ -		//filtered_types += " Animations,";  		filtered_types += LLTrans::getString("Animations");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Animations,";  		not_filtered_types += LLTrans::getString("Animations");  		filtered_by_all_types = FALSE; @@ -826,140 +783,120 @@ const std::string& LLInventoryFilter::getFilterText()  	if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD))  	{ -		//filtered_types += " Calling Cards,";  		filtered_types += LLTrans::getString("Calling Cards");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Calling Cards,";  		not_filtered_types += LLTrans::getString("Calling Cards");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE))  	{ -		//filtered_types += " Clothing,";  		filtered_types +=  LLTrans::getString("Clothing");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Clothing,";  		not_filtered_types +=  LLTrans::getString("Clothing");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE))  	{ -		//filtered_types += " Gestures,";  		filtered_types +=  LLTrans::getString("Gestures");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Gestures,";  		not_filtered_types +=  LLTrans::getString("Gestures");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK))  	{ -		//filtered_types += " Landmarks,";  		filtered_types +=  LLTrans::getString("Landmarks");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Landmarks,";  		not_filtered_types +=  LLTrans::getString("Landmarks");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD))  	{ -		//filtered_types += " Notecards,";  		filtered_types +=  LLTrans::getString("Notecards");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Notecards,";  		not_filtered_types +=  LLTrans::getString("Notecards");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT))  	{ -		//filtered_types += " Objects,";  		filtered_types +=  LLTrans::getString("Objects");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Objects,";  		not_filtered_types +=  LLTrans::getString("Objects");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_LSL))  	{ -		//filtered_types += " Scripts,";  		filtered_types +=  LLTrans::getString("Scripts");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Scripts,";  		not_filtered_types +=  LLTrans::getString("Scripts");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND))  	{ -		//filtered_types += " Sounds,";  		filtered_types +=  LLTrans::getString("Sounds");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Sounds,";  		not_filtered_types +=  LLTrans::getString("Sounds");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE))  	{ -		//filtered_types += " Textures,";  		filtered_types +=  LLTrans::getString("Textures");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Textures,";  		not_filtered_types +=  LLTrans::getString("Textures");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT))  	{ -		//filtered_types += " Snapshots,";  		filtered_types +=  LLTrans::getString("Snapshots");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Snapshots,";  		not_filtered_types +=  LLTrans::getString("Snapshots");  		filtered_by_all_types = FALSE;  	} @@ -975,7 +912,6 @@ const std::string& LLInventoryFilter::getFilterText()  		}  		else  		{ -			//mFilterText += "No ";  			mFilterText += LLTrans::getString("No Filters");  			mFilterText += not_filtered_types;  		} @@ -985,66 +921,55 @@ const std::string& LLInventoryFilter::getFilterText()  	if (isSinceLogoff())  	{ -		//mFilterText += " - Since Logoff";  		mFilterText += LLTrans::getString("Since Logoff");  	}  	return mFilterText;  } -void LLInventoryFilter::toLLSD(LLSD& data) const -{ -	data["filter_types"] = (LLSD::Integer)getFilterObjectTypes(); -	data["min_date"] = (LLSD::Integer)getMinDate(); -	data["max_date"] = (LLSD::Integer)getMaxDate(); -	data["hours_ago"] = (LLSD::Integer)getHoursAgo(); -	data["show_folder_state"] = (LLSD::Integer)getShowFolderState(); -	data["permissions"] = (LLSD::Integer)getFilterPermissions(); -	data["substring"] = (LLSD::String)getFilterSubString(); -	data["sort_order"] = (LLSD::Integer)getSortOrder(); -	data["since_logoff"] = (LLSD::Boolean)isSinceLogoff(); -} -void LLInventoryFilter::fromLLSD(LLSD& data) +LLInventoryFilter& LLInventoryFilter::operator=( const  LLInventoryFilter&  other )  { -	if(data.has("filter_types")) -	{ -		setFilterObjectTypes((U64)data["filter_types"].asInteger()); -	} - -	if(data.has("min_date") && data.has("max_date")) -	{ -		setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger()); -	} - -	if(data.has("hours_ago")) -	{ -		setHoursAgo((U32)data["hours_ago"].asInteger()); -	} - -	if(data.has("show_folder_state")) -	{ -		setShowFolderState((EFolderShow)data["show_folder_state"].asInteger()); -	} +	setFilterObjectTypes(other.getFilterObjectTypes()); +	setDateRange(other.getMinDate(), other.getMaxDate()); +	setHoursAgo(other.getHoursAgo()); +	setShowFolderState(other.getShowFolderState()); +	setFilterPermissions(other.getFilterPermissions()); +	setFilterSubString(other.getFilterSubString()); +	setDateRangeLastLogoff(other.isSinceLogoff()); +	return *this; +} -	if(data.has("permissions")) -	{ -		setFilterPermissions((PermissionMask)data["permissions"].asInteger()); -	} -	if(data.has("substring")) -	{ -		setFilterSubString(std::string(data["substring"].asString())); -	} +void LLInventoryFilter::toParams(Params& params) const +{ +	params.filter_ops.types = getFilterObjectTypes(); +	params.filter_ops.category_types = getFilterCategoryTypes(); +	params.filter_ops.wearable_types = getFilterWearableTypes(); +	params.filter_ops.date_range.min_date = getMinDate(); +	params.filter_ops.date_range.max_date = getMaxDate(); +	params.filter_ops.hours_ago = getHoursAgo(); +	params.filter_ops.show_folder_state = getShowFolderState(); +	params.filter_ops.permissions = getFilterPermissions(); +	params.substring = getFilterSubString(); +	params.since_logoff = isSinceLogoff(); +} -	if(data.has("sort_order")) +void LLInventoryFilter::fromParams(const Params& params) +{ +	if (!params.validateBlock())  	{ -		setSortOrder((U32)data["sort_order"].asInteger()); +		return;  	} -	if(data.has("since_logoff")) -	{ -		setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean()); -	} +	setFilterObjectTypes(params.filter_ops.types); +	setFilterCategoryTypes(params.filter_ops.category_types); +	setFilterWearableTypes(params.filter_ops.wearable_types); +	setDateRange(params.filter_ops.date_range.min_date,   params.filter_ops.date_range.max_date); +	setHoursAgo(params.filter_ops.hours_ago); +	setShowFolderState(params.filter_ops.show_folder_state); +	setFilterPermissions(params.filter_ops.permissions); +	setFilterSubString(params.substring); +	setDateRangeLastLogoff(params.since_logoff);  }  U64 LLInventoryFilter::getFilterObjectTypes() const @@ -1057,11 +982,21 @@ U64 LLInventoryFilter::getFilterCategoryTypes() const  	return mFilterOps.mFilterCategoryTypes;  } -BOOL LLInventoryFilter::hasFilterString() const +U64 LLInventoryFilter::getFilterWearableTypes() const +{ +	return mFilterOps.mFilterWearableTypes; +} + +bool LLInventoryFilter::hasFilterString() const  {  	return mFilterSubString.size() > 0;  } +std::string::size_type LLInventoryFilter::getFilterStringSize() const +{ +	return mFilterSubString.size(); +} +  PermissionMask LLInventoryFilter::getFilterPermissions() const  {  	return mFilterOps.mPermissions; @@ -1088,14 +1023,6 @@ LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const  {   	return mFilterOps.mShowFolderState;   } -U32 LLInventoryFilter::getSortOrder() const  -{  -	return mOrder;  -} -const std::string& LLInventoryFilter::getName() const  -{  -	return mName;  -}  void LLInventoryFilter::setFilterCount(S32 count)   {  @@ -1113,15 +1040,15 @@ void LLInventoryFilter::decrementFilterCount()  S32 LLInventoryFilter::getCurrentGeneration() const   {  -	return mFilterGeneration;  +	return mCurrentGeneration;  } -S32 LLInventoryFilter::getMinRequiredGeneration() const  +S32 LLInventoryFilter::getFirstSuccessGeneration() const  {  -	return mMinRequiredGeneration;  +	return mFirstSuccessGeneration;   } -S32 LLInventoryFilter::getMustPassGeneration() const  +S32 LLInventoryFilter::getFirstRequiredGeneration() const  {  -	return mMustPassGeneration;  +	return mFirstRequiredGeneration;   }  void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) @@ -1129,9 +1056,12 @@ void LLInventoryFilter::setEmptyLookupMessage(const std::string& message)  	mEmptyLookupMessage = message;  } -const std::string& LLInventoryFilter::getEmptyLookupMessage() const +std::string LLInventoryFilter::getEmptyLookupMessage() const  { -	return mEmptyLookupMessage; +	LLStringUtil::format_map_t args; +	args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig()); + +	return LLTrans::getString(mEmptyLookupMessage, args);  } @@ -1141,3 +1071,27 @@ bool LLInventoryFilter::areDateLimitsSet()  			|| mFilterOps.mMaxDate != time_max()  			|| mFilterOps.mHoursAgo != 0;  } + +bool LLInventoryFilter::showAllResults() const +{ +	return hasFilterString(); +} + + + +bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool   emit_errors /*= true*/ ) const +{ +	bool valid = LLInitParam::Block<DateRange>::validateBlock(emit_errors); +	if (valid) +	{ +		if (max_date() < min_date()) +		{ +			if (emit_errors) +			{ +				llwarns << "max_date should be greater or equal to min_date" <<   llendl; +			} +			valid = false; +		} +	} +	return valid; +} diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 9e600c036f..4912b5ca91 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -29,12 +29,13 @@  #include "llinventorytype.h"  #include "llpermissionsflags.h" +#include "llfolderviewmodel.h"  class LLFolderViewItem;  class LLFolderViewFolder;  class LLInventoryItem; -class LLInventoryFilter +class LLInventoryFilter : public LLFolderViewFilter  {  public:  	enum EFolderShow @@ -44,14 +45,6 @@ public:  		SHOW_NO_FOLDERS  	}; -	enum EFilterBehavior -	{ -		FILTER_NONE,				// nothing to do, already filtered -		FILTER_RESTART,				// restart filtering from scratch -		FILTER_LESS_RESTRICTIVE,	// existing filtered items will certainly pass this filter -		FILTER_MORE_RESTRICTIVE		// if you didn't pass the previous filter, you definitely won't pass this one -	}; -  	enum EFilterType	{  		FILTERTYPE_NONE = 0,  		FILTERTYPE_OBJECT = 0x1 << 0,	// normal default search-by-object-type @@ -59,7 +52,7 @@ public:  		FILTERTYPE_UUID	= 0x1 << 2,		// find the object with UUID and any links to it  		FILTERTYPE_DATE = 0x1 << 3,		// search by date range  		FILTERTYPE_WEARABLE = 0x1 << 4,	// search by wearable type -		FILTERTYPE_EMPTYFOLDERS = 0x1 << 5	// pass if folder is not a system folder to be hidden if empty +		FILTERTYPE_EMPTYFOLDERS = 0x1 << 5		// pass if folder is not a system   folder to be hidden if  	};  	enum EFilterLink @@ -77,16 +70,92 @@ public:  		SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2	// Force system folders to be on top  	}; -	LLInventoryFilter(const std::string& name); -	virtual ~LLInventoryFilter(); +	struct FilterOps +	{ +		struct DateRange : public LLInitParam::Block<DateRange> +		{ +			Optional<time_t>	min_date, +								max_date; + +			DateRange() +			:	min_date("min_date", time_min()), +				max_date("max_date", time_max()) +			{} + +			bool validateBlock(bool emit_errors = true) const; +		}; + +		struct Params : public LLInitParam::Block<Params> +		{ +			Optional<U32>				types; +			Optional<U64>				object_types, +										wearable_types, +										category_types; +			Optional<EFilterLink>		links; +			Optional<LLUUID>			uuid; +			Optional<DateRange>			date_range; +			Optional<S32>				hours_ago; +			Optional<EFolderShow>		show_folder_state; +			Optional<PermissionMask>	permissions; + +			Params() +			:	types("filter_types", FILTERTYPE_OBJECT), +				object_types("object_types", 0xffffFFFFffffFFFFULL), +				wearable_types("wearable_types", 0xffffFFFFffffFFFFULL), +				category_types("category_types", 0xffffFFFFffffFFFFULL), +				links("links", FILTERLINK_INCLUDE_LINKS), +				uuid("uuid"), +				date_range("date_range"), +				hours_ago("hours_ago", 0), +				show_folder_state("show_folder_state", SHOW_NON_EMPTY_FOLDERS), +				permissions("permissions", PERM_NONE) +			{} +		}; + +		FilterOps(const Params& = Params()); + +		U32 			mFilterTypes; +		U64				mFilterObjectTypes,   // For _OBJECT +						mFilterWearableTypes, +						mFilterLinks, +						mFilterCategoryTypes; // For _CATEGORY +		LLUUID      	mFilterUUID; 		  // for UUID + +		time_t			mMinDate, +						mMaxDate; +		U32				mHoursAgo; + +		EFolderShow		mShowFolderState; +		PermissionMask	mPermissions; +	}; +							 +	struct Params : public LLInitParam::Block<Params> +	{ +		Optional<std::string>		name; +		Optional<FilterOps::Params>	filter_ops; +		Optional<std::string>		substring; +		Optional<bool>				since_logoff; + +		Params() +		:	name("name"), +			filter_ops(""), +			substring("substring"), +			since_logoff("since_logoff") +		{} +	}; +									 +	LLInventoryFilter(const Params& p = Params()); +	LLInventoryFilter(const LLInventoryFilter& other) { *this = other; } +	virtual ~LLInventoryFilter() {}  	// +-------------------------------------------------------------------+  	// + Parameters  	// +-------------------------------------------------------------------+ -	void 				setFilterObjectTypes(U64 types);  	U64 				getFilterObjectTypes() const;  	U64					getFilterCategoryTypes() const; -	BOOL 				isFilterObjectTypesWith(LLInventoryType::EType t) const; +	U64					getFilterWearableTypes() const; +	bool 				isFilterObjectTypesWith(LLInventoryType::EType t) const; +	void 				setFilterObjectTypes(U64 types);  	void 				setFilterCategoryTypes(U64 types);  	void 				setFilterUUID(const LLUUID &object_id);  	void				setFilterWearableTypes(U64 types); @@ -96,7 +165,7 @@ public:  	void 				setFilterSubString(const std::string& string);  	const std::string& 	getFilterSubString(BOOL trim = FALSE) const;  	const std::string& 	getFilterSubStringOrig() const { return mFilterSubStringOrig; }  -	BOOL 				hasFilterString() const; +	bool 				hasFilterString() const;  	void 				setFilterPermissions(PermissionMask perms);  	PermissionMask 		getFilterPermissions() const; @@ -115,43 +184,35 @@ public:  	// +-------------------------------------------------------------------+  	// + Execution And Results  	// +-------------------------------------------------------------------+ -	BOOL 				check(const LLFolderViewItem* item); +	bool				check(const LLFolderViewModelItem* listener);  	bool				check(const LLInventoryItem* item); -	bool				checkFolder(const LLFolderViewFolder* folder) const; +	bool				checkFolder(const LLFolderViewModelItem* listener) const;  	bool				checkFolder(const LLUUID& folder_id) const; -	BOOL 				checkAgainstFilterType(const LLFolderViewItem* item) const; -	bool 				checkAgainstFilterType(const LLInventoryItem* item) const; -	BOOL 				checkAgainstPermissions(const LLFolderViewItem* item) const; -	bool 				checkAgainstPermissions(const LLInventoryItem* item) const; -	BOOL 				checkAgainstFilterLinks(const LLFolderViewItem* item) const; -	bool				checkAgainstClipboard(const LLUUID& object_id) const; -	std::string::size_type getStringMatchOffset() const; +	bool				showAllResults() const; +	std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const; +	std::string::size_type getFilterStringSize() const;  	// +-------------------------------------------------------------------+  	// + Presentation  	// +-------------------------------------------------------------------+  	void 				setShowFolderState( EFolderShow state);  	EFolderShow 		getShowFolderState() const; -	void 				setSortOrder(U32 order); -	U32 				getSortOrder() const; -  	void 				setEmptyLookupMessage(const std::string& message); -	const std::string&	getEmptyLookupMessage() const; +	std::string			getEmptyLookupMessage() const;  	// +-------------------------------------------------------------------+  	// + Status  	// +-------------------------------------------------------------------+ -	BOOL 				isActive() const; -	BOOL 				isModified() const; -	BOOL 				isModifiedAndClear(); -	BOOL 				isSinceLogoff() const; +	bool 				isActive() const; +	bool 				isModified() const; +	bool 				isSinceLogoff() const;  	void 				clearModified(); -	const std::string& 	getName() const; +	const std::string& 	getName() const { return mName; }  	const std::string& 	getFilterText();  	//RN: this is public to allow system to externally force a global refilter -	void 				setModified(EFilterBehavior behavior = FILTER_RESTART); +	void 				setModified(EFilterModified behavior = FILTER_RESTART);  	// +-------------------------------------------------------------------+  	// + Count @@ -163,8 +224,8 @@ public:  	// +-------------------------------------------------------------------+  	// + Default  	// +-------------------------------------------------------------------+ -	BOOL 				isDefault() const; -	BOOL 				isNotDefault() const; +	bool 				isDefault() const; +	bool 				isNotDefault() const;  	void 				markDefault();  	void 				resetDefault(); @@ -172,57 +233,42 @@ public:  	// + Generation  	// +-------------------------------------------------------------------+  	S32 				getCurrentGeneration() const; -	S32 				getMinRequiredGeneration() const; -	S32 				getMustPassGeneration() const; +	S32 				getFirstSuccessGeneration() const; +	S32 				getFirstRequiredGeneration() const; +  	// +-------------------------------------------------------------------+  	// + Conversion  	// +-------------------------------------------------------------------+ -	void 				toLLSD(LLSD& data) const; -	void 				fromLLSD(LLSD& data); +	void 				toParams(Params& params) const; +	void 				fromParams(const Params& p); + +	LLInventoryFilter& operator =(const LLInventoryFilter& other);  private:  	bool				areDateLimitsSet(); - -	struct FilterOps -	{ -		FilterOps(); -		U32 			mFilterTypes; - -		U64				mFilterObjectTypes; // For _OBJECT -		U64				mFilterWearableTypes; -		U64				mFilterCategoryTypes; // For _CATEGORY -		LLUUID      	mFilterUUID; // for UUID - -		time_t			mMinDate; -		time_t			mMaxDate; -		U32				mHoursAgo; -		EFolderShow		mShowFolderState; -		PermissionMask	mPermissions; -		U64				mFilterLinks; -	}; - -	U32						mOrder; -	U32 					mLastLogoff; +	bool 				checkAgainstFilterType(const class LLFolderViewModelItemInventory* listener) const; +	bool 				checkAgainstFilterType(const LLInventoryItem* item) const; +	bool 				checkAgainstPermissions(const class LLFolderViewModelItemInventory* listener) const; +	bool 				checkAgainstPermissions(const LLInventoryItem* item) const; +	bool 				checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const; +	bool				checkAgainstClipboard(const LLUUID& object_id) const;  	FilterOps				mFilterOps;  	FilterOps				mDefaultFilterOps; -	std::string::size_type	mSubStringMatchOffset;  	std::string				mFilterSubString;  	std::string				mFilterSubStringOrig;  	const std::string		mName; -	S32						mFilterGeneration; -	S32						mMustPassGeneration; -	S32						mMinRequiredGeneration; +	S32						mCurrentGeneration; +	S32						mFirstRequiredGeneration; +	S32						mFirstSuccessGeneration;  	S32						mNextFilterGeneration;  	S32						mFilterCount; -	EFilterBehavior 		mFilterBehavior; +	EFilterModified 		mFilterModified; -	BOOL 					mModified; -	BOOL 					mNeedTextRebuild;  	std::string 			mFilterText;  	std::string 			mEmptyLookupMessage;  }; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ab5b082915..1ae6fd91ce 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -45,7 +45,7 @@  // newview includes  #include "llappearancemgr.h"  #include "llappviewer.h" -//#include "llfirstuse.h" +#include "llclipboard.h"  #include "llfloaterinventory.h"  #include "llfloatersidepanelcontainer.h"  #include "llfocusmgr.h" @@ -74,8 +74,10 @@  #include "llsidepanelinventory.h"  #include "lltabcontainer.h"  #include "lltooldraganddrop.h" +#include "lltrans.h"  #include "lluictrlfactory.h"  #include "llviewermessage.h" +#include "llviewerfoldertype.h"  #include "llviewerobjectlist.h"  #include "llviewerregion.h"  #include "llviewerwindow.h" @@ -440,7 +442,7 @@ void show_item_original(const LLUUID& item_uuid)  	//sidetray inventory panel  	LLSidepanelInventory *sidepanel_inventory =	LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); -	bool reset_inventory_filter = !floater_inventory->isInVisibleChain(); +	bool do_reset_inventory_filter = !floater_inventory->isInVisibleChain();  	LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel();  	if (!active_panel)  @@ -460,37 +462,49 @@ void show_item_original(const LLUUID& item_uuid)  	}  	active_panel->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_NO); -	if(reset_inventory_filter) +	if(do_reset_inventory_filter)  	{ -		//inventory floater -		bool floater_inventory_visible = false; +		reset_inventory_filter(); +	} +} + + +void reset_inventory_filter() +{ +	//inventory floater +	bool floater_inventory_visible = false; -		LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); -		for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) +	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); +	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) +	{ +		LLFloaterInventory* floater_inventory = dynamic_cast<LLFloaterInventory*>(*iter); +		if (floater_inventory)  		{ -			LLFloaterInventory* floater_inventory = dynamic_cast<LLFloaterInventory*>(*iter); -			if (floater_inventory) -			{ -				LLPanelMainInventory* main_inventory = floater_inventory->getMainInventoryPanel(); +			LLPanelMainInventory* main_inventory = floater_inventory->getMainInventoryPanel(); -				main_inventory->onFilterEdit(""); +			main_inventory->onFilterEdit(""); -				if(floater_inventory->getVisible()) -				{ -					floater_inventory_visible = true; -				} +			if(floater_inventory->getVisible()) +			{ +				floater_inventory_visible = true;  			}  		} -		if(sidepanel_inventory && !floater_inventory_visible) +	} + +	if(!floater_inventory_visible) +	{ +		LLSidepanelInventory *sidepanel_inventory =	LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); +		if (sidepanel_inventory)  		{  			LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); - -			main_inventory->onFilterEdit(""); +			if (main_inventory) +			{ +				main_inventory->onFilterEdit(""); +			}  		}  	}  } -  void open_outbox()  {  	LLFloaterReg::showInstance("outbox"); @@ -948,7 +962,7 @@ void LLSaveFolderState::setApply(BOOL apply)  void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)  {  	LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); -	LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); +	LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getViewModelItem();  	if(!bridge) return;  	if(mApply) @@ -983,7 +997,7 @@ void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)  void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)  { -	if (item->getFiltered()) +	if (item->passedFilter())  	{  		item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);  	} @@ -991,12 +1005,12 @@ void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)  void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)  { -	if (folder->getFiltered() && folder->getParentFolder()) +	if (folder->LLFolderViewItem::passedFilter() && folder->getParentFolder())  	{  		folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);  	}  	// if this folder didn't pass the filter, and none of its descendants did -	else if (!folder->getFiltered() && !folder->hasFilteredDescendants()) +	else if (!folder->getViewModelItem()->passedFilter() && !folder->getViewModelItem()->descendantsPassedFilter())  	{  		folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);  	} @@ -1004,7 +1018,7 @@ void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)  void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)  { -	if (item->getFiltered() && !mItemSelected) +	if (item->passedFilter() && !mItemSelected)  	{  		item->getRoot()->setSelection(item, FALSE, FALSE);  		if (item->getParentFolder()) @@ -1017,7 +1031,7 @@ void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)  void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)  { -	if (folder->getFiltered() && !mItemSelected) +	if (folder->LLFolderViewItem::passedFilter() && !mItemSelected)  	{  		folder->getRoot()->setSelection(folder, FALSE, FALSE);  		if (folder->getParentFolder()) @@ -1044,3 +1058,87 @@ void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)  	}  } +void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action) +{ +	if ("rename" == action) +	{ +		root->startRenamingSelectedItem(); +		return; +	} +	if ("delete" == action) +	{ +		LLSD args; +		args["QUESTION"] = LLTrans::getString(root->getNumSelectedItems() > 1 ? "DeleteItems" :  "DeleteItem"); +		LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root)); +		return; +	} +	if (("copy" == action) || ("cut" == action)) +	{	 +		// Clear the clipboard before we start adding things on it +		LLClipboard::instance().reset(); +	} + +	static const std::string change_folder_string = "change_folder_type_"; +	if (action.length() > change_folder_string.length() &&  +		(action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) +	{ +		LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); +		LLFolderViewModelItemInventory* inventory_item = static_cast<LLFolderViewModelItemInventory*>(root->getViewModelItem()); +		LLViewerInventoryCategory *cat = model->getCategory(inventory_item->getUUID()); +		if (!cat) return; +		cat->changeType(new_folder_type); +		return; +	} + + +	std::set<LLFolderViewItem*> selected_items = root->getSelectionList(); + +	LLMultiPreview* multi_previewp = NULL; +	LLMultiProperties* multi_propertiesp = NULL; + +	if (("task_open" == action  || "open" == action) && selected_items.size() > 1) +	{ +		multi_previewp = new LLMultiPreview(); +		gFloaterView->addChild(multi_previewp); + +		LLFloater::setFloaterHost(multi_previewp); + +	} +	else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) +	{ +		multi_propertiesp = new LLMultiProperties(); +		gFloaterView->addChild(multi_propertiesp); + +		LLFloater::setFloaterHost(multi_propertiesp); +	} + +	std::set<LLFolderViewItem*>::iterator set_iter; + +	for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) +	{ +		LLFolderViewItem* folder_item = *set_iter; +		if(!folder_item) continue; +		LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); +		if(!bridge) continue; +		bridge->performAction(model, action); +	} + +	LLFloater::setFloaterHost(NULL); +	if (multi_previewp) +	{ +		multi_previewp->openFloater(LLSD()); +	} +	else if (multi_propertiesp) +	{ +		multi_propertiesp->openFloater(LLSD()); +	} +} + +void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, const LLSD& response, LLFolderView* root ) +{ +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	if (option == 0) +	{ +		root->removeSelectedItems(); +	} +} diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 5cf9c528b0..11fc17ce9b 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -56,6 +56,7 @@ void show_item_profile(const LLUUID& item_uuid);  void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id);  void show_item_original(const LLUUID& item_uuid); +void reset_inventory_filter();  void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); @@ -418,21 +419,6 @@ public:  class LLFolderViewItem;  class LLFolderViewFolder; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFunctor -// -// Simple abstract base class for applying a functor to folders and -// items in a folder view hierarchy. This is suboptimal for algorithms -// that only work folders or only work on items, but I'll worry about -// that later when it's determined to be too slow. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLFolderViewFunctor -{ -public: -	virtual ~LLFolderViewFunctor() {} -	virtual void doFolder(LLFolderViewFolder* folder) = 0; -	virtual void doItem(LLFolderViewItem* item) = 0; -};  class LLInventoryState  { @@ -442,49 +428,13 @@ public:  	static LLUUID sWearNewClothingTransactionID;	// wear all clothing in this transaction	  }; -class LLSelectFirstFilteredItem : public LLFolderViewFunctor +struct LLInventoryAction  { -public: -	LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} -	virtual ~LLSelectFirstFilteredItem() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); -	BOOL wasItemSelected() { return mItemSelected; } -protected: -	BOOL mItemSelected; -}; +	static void doToSelected(class LLInventoryModel* model, class LLFolderView* root, const std::string& action); -class LLOpenFilteredFolders : public LLFolderViewFunctor -{ -public: -	LLOpenFilteredFolders()  {} -	virtual ~LLOpenFilteredFolders() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); +	static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLFolderView* root);  }; -class LLSaveFolderState : public LLFolderViewFunctor -{ -public: -	LLSaveFolderState() : mApply(FALSE) {} -	virtual ~LLSaveFolderState() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item) {} -	void setApply(BOOL apply); -	void clearOpenFolders() { mOpenFolders.clear(); } -protected: -	std::set<LLUUID> mOpenFolders; -	BOOL mApply; -}; - -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: -	LLOpenFoldersWithSelection() {} -	virtual ~LLOpenFoldersWithSelection() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); -};  #endif // LL_LLINVENTORYFUNCTIONS_H diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6e23d7c701..0673970d89 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -373,13 +373,12 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id)  // specifies 'type' as what it defaults to containing. The category is  // not necessarily only for that type. *NOTE: This will create a new  // inventory category on the fly if one does not exist. -const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type,  -													   bool create_folder,  -													   bool find_in_library) +const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder/*,  +					  bool find_in_library*/)  {  	LLUUID rv = LLUUID::null; -	const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID(); +	const LLUUID &root_id = /*(find_in_library) ? gInventory.getLibraryRootFolderID() :*/ gInventory.getRootFolderID();  	if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)  	{  		rv = root_id; @@ -402,7 +401,44 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe  		}  	} -	if(rv.isNull() && isInventoryUsable() && (create_folder && !find_in_library)) +	if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/)) +	{ +		if(root_id.notNull()) +		{ +			return createNewCategory(root_id, preferred_type, LLStringUtil::null); +		} +	} +	return rv; +} + +const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder) +{ +	LLUUID rv = LLUUID::null; + +	const LLUUID &root_id = gInventory.getLibraryRootFolderID(); +	if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) +	{ +		rv = root_id; +	} +	else if (root_id.notNull()) +	{ +		cat_array_t* cats = NULL; +		cats = get_ptr_in_map(mParentChildCategoryTree, root_id); +		if(cats) +		{ +			S32 count = cats->count(); +			for(S32 i = 0; i < count; ++i) +			{ +				if(cats->get(i)->getPreferredType() == preferred_type) +				{ +					rv = cats->get(i)->getUUID(); +					break; +				} +			} +		} +	} + +	if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/))  	{  		if(root_id.notNull())  		{ @@ -1245,14 +1281,33 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id)  							   items,  							   INCLUDE_TRASH);  			S32 count = items.count(); + +			item_map_t::iterator item_map_end = mItemMap.end(); +			cat_map_t::iterator cat_map_end = mCategoryMap.end(); +			LLUUID uu_id; +  			for(S32 i = 0; i < count; ++i)  			{ -				deleteObject(items.get(i)->getUUID()); +				uu_id = items.get(i)->getUUID(); + +				// This check prevents the deletion of a previously deleted item. +				// This is necessary because deletion is not done in a hierarchical +				// order. The current item may have been already deleted as a child +				// of its deleted parent. +				if (mItemMap.find(uu_id) != item_map_end) +				{ +					deleteObject(uu_id); +				}  			} +  			count = categories.count();  			for(S32 i = 0; i < count; ++i)  			{ -				deleteObject(categories.get(i)->getUUID()); +				uu_id = categories.get(i)->getUUID(); +				if (mCategoryMap.find(uu_id) != cat_map_end) +				{ +					deleteObject(uu_id); +				}  			}  		}  	} @@ -3239,68 +3294,7 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c  	}  } -//* @param[in] items vector of items in order to be saved. -void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items) -{ -	int sortField = 0; - -	// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field -	for (item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) -	{ -		LLViewerInventoryItem* item = *i; - -		item->setSortField(++sortField); -		item->setComplete(TRUE); -		item->updateServer(FALSE); - -		updateItem(item); - -		// Tell the parent folder to refresh its sort order. -		addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); -	} - -	notifyObservers(); -} - -// See also LLInventorySort where landmarks in the Favorites folder are sorted. -class LLViewerInventoryItemSort -{ -public: -	bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) -	{ -		return a->getSortField() < b->getSortField(); -	} -}; -/** - * Sorts passed items by LLViewerInventoryItem sort field. - * - * @param[in, out] items - array of items, not sorted. - */ -static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) -{ -	static LLViewerInventoryItemSort sort_functor; -	std::sort(items.begin(), items.end(), sort_functor); -} - -// * @param source_item_id - LLUUID of the source item to be moved into new position -// * @param target_item_id - LLUUID of the target item before which source item should be placed. -void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) -{ -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	LLIsType is_type(LLAssetType::AT_LANDMARK); -	LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - -	// ensure items are sorted properly before changing order. EXT-3498 -	rearrange_item_order_by_sort_field(items); - -	// update order -	updateItemsOrder(items, source_item_id, target_item_id); - -	saveItemsOrder(items); -}  //---------------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 8382e875b4..503de627a0 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -231,11 +231,12 @@ public:  	// Returns the uuid of the category that specifies 'type' as what it   	// defaults to containing. The category is not necessarily only for that type.   	//    NOTE: If create_folder is true, this will create a new inventory category  -	//    on the fly if one does not exist. *NOTE: if find_in_library is true it  -	//    will search in the user's library folder instead of "My Inventory" +	//    on the fly if one does not exist.   	const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type,  -										 bool create_folder = true,  -										 bool find_in_library = false); +										 bool create_folder = true); +	//    will search in the user's library folder instead of "My Inventory" +	const LLUUID findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type,  +												bool create_folder = true);  	// Get whatever special folder this object is a child of, if any.  	const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const; @@ -362,15 +363,6 @@ public:  	// Returns end() of the vector if not found.  	static LLInventoryModel::item_array_t::iterator findItemIterByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id); -	// Saves current order of the passed items using inventory item sort field. -	// Resets 'items' sort fields and saves them on server. -	// Is used to save order for Favorites folder. -	void saveItemsOrder(const LLInventoryModel::item_array_t& items); - -	// Rearranges Landmarks inside Favorites folder. -	// Moves source landmark before target one. -	void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); -  	//--------------------------------------------------------------------  	// Creation  	//-------------------------------------------------------------------- diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 71dd963f28..03dfada77c 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -38,11 +38,13 @@  #include "llfloaterreg.h"  #include "llfloatersidepanelcontainer.h"  #include "llfolderview.h" +#include "llfolderviewitem.h"  #include "llimfloater.h"  #include "llimview.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llinventorymodelbackgroundfetch.h" +#include "llpreview.h"  #include "llsidepanelinventory.h"  #include "llviewerattachmenu.h"  #include "llviewerfoldertype.h" @@ -53,8 +55,7 @@ static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");  const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");  const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");  const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); -static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; - +static const LLInventoryFolderViewModelBuilder INVENTORY_BRIDGE_BUILDER;  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLInventoryPanelObserver @@ -134,13 +135,12 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :  	mAllowMultiSelect(p.allow_multi_select),  	mShowItemLinkOverlays(p.show_item_link_overlays),  	mShowEmptyMessage(p.show_empty_message), -	mShowLoadStatus(p.show_load_status),  	mViewsInitialized(false),  	mInvFVBridgeBuilder(NULL)  {  	mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; -	// contex menu callbacks +	// context menu callbacks  	mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2));  	mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));  	mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); @@ -151,61 +151,62 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :  } -void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) +LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )  { -	// Determine the root folder in case specified, and -	// build the views starting with that folder. -	 -	std::string start_folder_name(params.start_folder()); +    LLFolderView::Params p(mParams.folder_view); +    p.name = getName(); +    p.title = getLabel(); +    p.rect = LLRect(0, 0, getRect().getWidth(), 0); +    p.parent_panel = this; +    p.tool_tip = p.name; +    p.listener = mInvFVBridgeBuilder->createBridge(	LLAssetType::AT_CATEGORY, +        LLAssetType::AT_CATEGORY, +        LLInventoryType::IT_CATEGORY, +        this, +        &mInventoryViewModel, +        NULL, +        root_id); +    p.view_model = &mInventoryViewModel; +    p.use_label_suffix = mParams.use_label_suffix; +    p.allow_multiselect = mAllowMultiSelect; +    p.show_empty_message = mShowEmptyMessage; +    p.show_item_link_overlays = mShowItemLinkOverlays; +    p.root = NULL; + +    return LLUICtrlFactory::create<LLFolderView>(p); +} -	const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(start_folder_name); - -	LLUUID root_id; - -	if ("LIBRARY" == params.start_folder()) -	{ -		root_id = gInventory.getLibraryRootFolderID(); -	} -	else +void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  	{ -		root_id = (preferred_type != LLFolderType::FT_NONE) -				? gInventory.findCategoryUUIDForType(preferred_type, false, false)  -				: LLUUID::null; -	} -	 -	if ((root_id == LLUUID::null) && !start_folder_name.empty()) +	// save off copy of params +	mParams = params; +	// Clear up the root view +	// Note: This needs to be done *before* we build the new folder view  +	LLUUID root_id = getRootFolderID(); +	if (mFolderRoot)  	{ -		llwarns << "No category found that matches start_folder: " << start_folder_name << llendl; -		root_id = LLUUID::generateNewID(); +		removeItemID(root_id); +		mFolderRoot->destroyView(); +		mFolderRoot = NULL;  	} -	LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, -																	LLAssetType::AT_CATEGORY, -																	LLInventoryType::IT_CATEGORY, -																	this, -																	NULL, -																	root_id); -	 -	mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); -} - -void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) -{  	LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD); - +	  	mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves +	{ +		// Determine the root folder in case specified, and +		// build the views starting with that folder. +		mFolderRoot = createFolderRoot(root_id); -	buildFolderView(params); - +		addItemID(root_id, mFolderRoot); +}  	mCommitCallbackRegistrar.popScope(); -	  	mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);  	// Scroller -	{  		LLRect scroller_view_rect = getRect();  		scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); -		LLScrollContainer::Params scroller_params(params.scroll()); +	LLScrollContainer::Params scroller_params(mParams.scroll());  		scroller_params.rect(scroller_view_rect);  		mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);  		addChild(mScroller); @@ -213,7 +214,6 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  		mFolderRoot->setScrollContainer(mScroller);  		mFolderRoot->setFollowsAll();  		mFolderRoot->addChild(mFolderRoot->mStatusTextBox); -	}  	// Set up the callbacks from the inventory we're viewing, and then build everything.  	mInventoryObserver = new LLInventoryPanelObserver(this); @@ -228,6 +228,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  	{  		initializeViews();  	} +	  	gIdleCallbacks.addFunction(onIdle, (void*)this);  	if (mSortOrderSetting != INHERIT_SORT_ORDER) @@ -240,32 +241,31 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  	}  	// hide inbox -	getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); -	getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); +	getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); +	getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX));  	// set the filter for the empty folder if the debug setting is on  	if (gSavedSettings.getBOOL("DebugHideEmptySystemFolders"))  	{ -		getFilter()->setFilterEmptySystemFolders(); +		getFilter().setFilterEmptySystemFolders();  	}  	// keep track of the clipboard state so that we avoid filtering too much  	mClipboardState = LLClipboard::instance().getGeneration();  	// Initialize base class params. -	LLPanel::initFromParams(params); +	LLPanel::initFromParams(mParams);  }  LLInventoryPanel::~LLInventoryPanel()  { -	if (mFolderRoot) -	{ -		U32 sort_order = mFolderRoot->getSortOrder(); +	gIdleCallbacks.deleteFunction(idle, this); + +	U32 sort_order = getFolderViewModel()->getSorter().getSortOrder();  		if (mSortOrderSetting != INHERIT_SORT_ORDER)  		{  			gSavedSettings.setU32(mSortOrderSetting, sort_order);  		} -	}  	gIdleCallbacks.deleteFunction(onIdle, this); @@ -281,82 +281,68 @@ LLInventoryPanel::~LLInventoryPanel()  void LLInventoryPanel::draw()  {  	// Select the desired item (in case it wasn't loaded when the selection was requested) -	mFolderRoot->updateSelection(); -	 -	// Nudge the filter if the clipboard state changed -	if (mClipboardState != LLClipboard::instance().getGeneration()) -	{ -		mClipboardState = LLClipboard::instance().getGeneration(); -		getFilter()->setModified(LLClipboard::instance().isCutMode() ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE : LLInventoryFilter::FILTER_LESS_RESTRICTIVE); -	} +	updateSelection();  	LLPanel::draw();  } -LLInventoryFilter* LLInventoryPanel::getFilter() +const LLInventoryFilter& LLInventoryPanel::getFilter() const  { -	if (mFolderRoot)  -	{ -		return mFolderRoot->getFilter(); +	return getFolderViewModel()->getFilter();  	} -	return NULL; -} -const LLInventoryFilter* LLInventoryPanel::getFilter() const +LLInventoryFilter& LLInventoryPanel::getFilter()  { -	if (mFolderRoot) -	{ -		return mFolderRoot->getFilter(); -	} -	return NULL; +	return getFolderViewModel()->getFilter();  }  void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type)  {  	if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT) -		getFilter()->setFilterObjectTypes(types); +		getFilter().setFilterObjectTypes(types);  	if (filter_type == LLInventoryFilter::FILTERTYPE_CATEGORY) -		getFilter()->setFilterCategoryTypes(types); +		getFilter().setFilterCategoryTypes(types);  }  U32 LLInventoryPanel::getFilterObjectTypes() const   {  -	return mFolderRoot->getFilterObjectTypes();  +	return getFilter().getFilterObjectTypes();  }  U32 LLInventoryPanel::getFilterPermMask() const   {  -	return mFolderRoot->getFilterPermissions();  +	return getFilter().getFilterPermissions();  }  void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)  { -	getFilter()->setFilterPermissions(filter_perm_mask); +	getFilter().setFilterPermissions(filter_perm_mask);  }  void LLInventoryPanel::setFilterWearableTypes(U64 types)  { -	getFilter()->setFilterWearableTypes(types); +	getFilter().setFilterWearableTypes(types);  }  void LLInventoryPanel::setFilterSubString(const std::string& string)  { -	getFilter()->setFilterSubString(string); +	getFilter().setFilterSubString(string);  }  const std::string LLInventoryPanel::getFilterSubString()   {  -	return mFolderRoot->getFilterSubString();  +	return getFilter().getFilterSubString();  }  void LLInventoryPanel::setSortOrder(U32 order)  { -	getFilter()->setSortOrder(order); -	if (getFilter()->isModified()) +    LLInventorySort sorter(order); +	if (order != getFolderViewModel()->getSorter().getSortOrder())  	{ -		mFolderRoot->setSortOrder(order); +		getFolderViewModel()->setSorter(sorter); +		mFolderRoot->arrangeAll();  		// try to keep selection onscreen, even if it wasn't to start with  		mFolderRoot->scrollToShowSelection();  	} @@ -364,37 +350,32 @@ void LLInventoryPanel::setSortOrder(U32 order)  U32 LLInventoryPanel::getSortOrder() const   {  -	return mFolderRoot->getSortOrder();  -} - -void LLInventoryPanel::requestSort() -{ -	mFolderRoot->requestSort(); +	return getFolderViewModel()->getSorter().getSortOrder();  }  void LLInventoryPanel::setSinceLogoff(BOOL sl)  { -	getFilter()->setDateRangeLastLogoff(sl); +	getFilter().setDateRangeLastLogoff(sl);  }  void LLInventoryPanel::setHoursAgo(U32 hours)  { -	getFilter()->setHoursAgo(hours); +	getFilter().setHoursAgo(hours);  }  void LLInventoryPanel::setFilterLinks(U64 filter_links)  { -	getFilter()->setFilterLinks(filter_links); +	getFilter().setFilterLinks(filter_links);  }  void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show)  { -	getFilter()->setShowFolderState(show); +	getFilter().setShowFolderState(show);  }  LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()  { -	return getFilter()->getShowFolderState(); +	return getFilter().getShowFolderState();  }  void LLInventoryPanel::modelChanged(U32 mask) @@ -418,11 +399,20 @@ void LLInventoryPanel::modelChanged(U32 mask)  	{  		const LLUUID& item_id = (*items_iter);  		const LLInventoryObject* model_item = model->getObject(item_id); -		LLFolderViewItem* view_item = mFolderRoot->getItemByID(item_id); +		LLFolderViewItem* view_item = getItemByID(item_id); +		LLFolderViewModelItemInventory* viewmodel_item =  +			static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);  		// LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item  		// to folder is the fast way to get a folder without searching through folders tree. -		LLFolderViewFolder* view_folder = dynamic_cast<LLFolderViewFolder*>(view_item); +		LLFolderViewFolder* view_folder = NULL; + +		// Check requires as this item might have already been deleted +		// as a child of its deleted parent. +		if (model_item && view_item) +		{ +			view_folder = dynamic_cast<LLFolderViewFolder*>(view_item); +		}  		//////////////////////////////  		// LABEL Operation @@ -433,7 +423,7 @@ void LLInventoryPanel::modelChanged(U32 mask)  			if (view_item)  			{  				// Request refresh on this item (also flags for filtering) -				LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getListener(); +				LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getViewModelItem();  				if(bridge)  				{	// Clear the display name first, so it gets properly re-built during refresh()  					bridge->clearDisplayName(); @@ -449,11 +439,14 @@ void LLInventoryPanel::modelChanged(U32 mask)  		if (mask & LLInventoryObserver::REBUILD)  		{  			handled = true; -			if (model_item && view_item) +			if (model_item && view_item && viewmodel_item)  			{  				view_item->destroyView(); +				removeItemID(viewmodel_item->getUUID());  			}  			view_item = buildNewViews(item_id); +			viewmodel_item =  +				static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);  			view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);  		} @@ -475,7 +468,7 @@ void LLInventoryPanel::modelChanged(U32 mask)  		{  			if (view_folder)  			{ -				view_folder->requestSort(); +				view_folder->getViewModelItem()->requestSort();  			}  		}	 @@ -510,20 +503,24 @@ void LLInventoryPanel::modelChanged(U32 mask)  			else if (model_item && view_item)  			{  				// Don't process the item if it is the root -				if (view_item->getRoot() != view_item) +				if (view_item->getParentFolder())  				{ -					LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot->getItemByID(model_item->getParentUUID()); +					LLFolderViewFolder* new_parent =   (LLFolderViewFolder*)getItemByID(model_item->getParentUUID());  					// Item has been moved.  					if (view_item->getParentFolder() != new_parent)  					{  						if (new_parent != NULL)  						{  							// Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. -							view_item->getParentFolder()->extractItem(view_item); -							view_item->addToFolder(new_parent, mFolderRoot); +							view_item->addToFolder(new_parent); +							addItemID(viewmodel_item->getUUID(), view_item);  						}  						else   						{ +							// Remove the item ID before destroying the view because the view-model-item gets +							// destroyed when the view is destroyed +                            removeItemID(viewmodel_item->getUUID()); +  							// Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that   							// doesn't include trash).  Just remove the item's UI.  							view_item->destroyView(); @@ -535,9 +532,10 @@ void LLInventoryPanel::modelChanged(U32 mask)  			//////////////////////////////  			// REMOVE Operation  			// This item has been removed from memory, but its associated UI element still exists. -			else if (!model_item && view_item) +			else if (!model_item && view_item && viewmodel_item)  			{  				// Remove the item's UI. +                removeItemID(viewmodel_item->getUUID());  				view_item->destroyView();  			}  		} @@ -549,6 +547,43 @@ LLFolderView* LLInventoryPanel::getRootFolder()  	return mFolderRoot;   } +LLUUID LLInventoryPanel::getRootFolderID() +{ +	if (mFolderRoot && mFolderRoot->getViewModelItem()) +	{ +		return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot->getViewModelItem())->getUUID(); + +	} +	else +	{ +		LLUUID root_id; +		if (mParams.start_folder.id.isChosen()) +		{ +			root_id = mParams.start_folder.id; +		} +		else +		{ +			const LLFolderType::EType preferred_type = mParams.start_folder.type.isChosen()  +				? mParams.start_folder.type +				: LLViewerFolderType::lookupTypeFromNewCategoryName(mParams.start_folder.name); + +			if ("LIBRARY" == mParams.start_folder.name()) +			{ +				root_id = gInventory.getLibraryRootFolderID(); +			} +			else if (preferred_type != LLFolderType::FT_NONE) +			{ +				root_id = gInventory.findCategoryUUIDForType(preferred_type, false); +				if (root_id.isNull()) +				{ +					llwarns << "Could not find folder of type " << preferred_type << llendl; +					root_id.generateNewID(); +				} +			} +		} +		return root_id; +	} +}  // static  void LLInventoryPanel::onIdle(void *userdata) @@ -568,16 +603,72 @@ void LLInventoryPanel::onIdle(void *userdata)  	}  } -const LLUUID& LLInventoryPanel::getRootFolderID() const +struct DirtyFilterFunctor : public LLFolderViewFunctor  { -	return mFolderRoot->getListener()->getUUID(); +	/*virtual*/ void doFolder(LLFolderViewFolder* folder) +	{ +		folder->getViewModelItem()->dirtyFilter(); +	} +	/*virtual*/ void doItem(LLFolderViewItem* item) +	{ +		item->getViewModelItem()->dirtyFilter(); +	} +}; + +void LLInventoryPanel::idle(void* user_data) +{ +	LLInventoryPanel* panel = (LLInventoryPanel*)user_data; +	// Nudge the filter if the clipboard state changed +	if (panel->mClipboardState != LLClipboard::instance().getGeneration()) +	{ +		panel->mClipboardState = LLClipboard::instance().getGeneration(); +		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); +		LLFolderViewFolder* trash_folder = panel->getFolderByID(trash_id); +		if (trash_folder) +		{ +            DirtyFilterFunctor dirtyFilterFunctor; +			trash_folder->applyFunctorToChildren(dirtyFilterFunctor); +		} + +	} + +	panel->mFolderRoot->update(); +	// while dragging, update selection rendering to reflect single/multi drag status +	if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) +	{ +		EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); +		if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) +		{ +			panel->mFolderRoot->setShowSingleSelection(TRUE); +		} +		else +		{ +			panel->mFolderRoot->setShowSingleSelection(FALSE); +		} +	} +	else +	{ +		panel->mFolderRoot->setShowSingleSelection(FALSE); +	}  } +  void LLInventoryPanel::initializeViews()  {  	if (!gInventory.isInventoryUsable()) return; -	rebuildViewsFor(getRootFolderID()); +	LLUUID root_id = getRootFolderID(); +	if (root_id.notNull()) +	{ +		buildNewViews(getRootFolderID()); +	} +	else +	{ +		buildNewViews(gInventory.getRootFolderID()); +		buildNewViews(gInventory.getLibraryRootFolderID()); +	} + +	gIdleCallbacks.addFunction(idle, this);  	mViewsInitialized = true; @@ -587,14 +678,14 @@ void LLInventoryPanel::initializeViews()  	if (gAgent.isFirstLogin())  	{  		// Auto open the user's library -		LLFolderViewFolder* lib_folder = mFolderRoot->getFolderByID(gInventory.getLibraryRootFolderID()); +		LLFolderViewFolder* lib_folder =   getFolderByID(gInventory.getLibraryRootFolderID());  		if (lib_folder)  		{  			lib_folder->setOpen(TRUE);  		}  		// Auto close the user's my inventory folder -		LLFolderViewFolder* my_inv_folder = mFolderRoot->getFolderByID(gInventory.getRootFolderID()); +		LLFolderViewFolder* my_inv_folder =   getFolderByID(gInventory.getRootFolderID());  		if (my_inv_folder)  		{  			my_inv_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); @@ -602,54 +693,12 @@ void LLInventoryPanel::initializeViews()  	}  } -LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id) -{ -	// Destroy the old view for this ID so we can rebuild it. -	LLFolderViewItem* old_view = mFolderRoot->getItemByID(id); -	if (old_view) -	{ -		old_view->destroyView(); -	} - -	return buildNewViews(id); -} - -LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix) -{ -	LLRect folder_rect(0, -					   0, -					   getRect().getWidth(), -					   0); - -	LLFolderView::Params p; -	 -	p.name = getName(); -	p.title = getLabel(); -	p.rect = folder_rect; -	p.parent_panel = this; -	p.tool_tip = p.name; -	p.listener =  bridge; -	p.use_label_suffix = useLabelSuffix; -	p.allow_multiselect = mAllowMultiSelect; -	p.show_empty_message = mShowEmptyMessage; -	p.show_load_status = mShowLoadStatus; - -	return LLUICtrlFactory::create<LLFolderView>(p); -}  LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)  { -	LLFolderViewFolder::Params params; +	LLFolderViewFolder::Params params(mParams.folder);  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -	  	params.root = mFolderRoot;  	params.listener = bridge;  	params.tool_tip = params.name; @@ -659,17 +708,9 @@ LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * br  LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge)  { -	LLFolderViewItem::Params params; +	LLFolderViewItem::Params params(mParams.item);  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -  	params.creation_date = bridge->getCreationDate();  	params.root = mFolderRoot;  	params.listener = bridge; @@ -682,20 +723,15 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge  LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)  {   	LLInventoryObject const* objectp = gInventory.getObject(id); - 	LLUUID root_id = mFolderRoot->getListener()->getUUID(); - 	LLFolderViewFolder* parent_folder = NULL; -	LLFolderViewItem* itemp = NULL; - 	if (id == root_id) - 	{ - 		parent_folder = mFolderRoot; - 	} - 	else if (objectp) - 	{ +	if (!objectp) return NULL; + +	LLFolderViewItem* folder_view_item = getItemByID(id); +   		const LLUUID &parent_id = objectp->getParentUUID(); - 		parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id); +	LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); -  		if (parent_folder) + 	if (!folder_view_item && parent_folder)    		{    			if (objectp->getType() <= LLAssetType::AT_NONE ||    				objectp->getType() >= LLAssetType::AT_COUNT) @@ -713,16 +749,12 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)    																				objectp->getType(),    																				LLInventoryType::IT_CATEGORY,    																				this, +																			&mInventoryViewModel,    																				mFolderRoot,    																				objectp->getUUID());    				if (new_listener)    				{ -					LLFolderViewFolder* folderp = createFolderViewFolder(new_listener); -					if (folderp) -					{ -						folderp->setItemSortOrder(mFolderRoot->getSortOrder()); -					} -  					itemp = folderp; +				folder_view_item = createFolderViewFolder(new_listener);    				}    			}    			else @@ -733,28 +765,28 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)    																				item->getActualType(),    																				item->getInventoryType(),    																				this, +																			&mInventoryViewModel,    																				mFolderRoot,    																				item->getUUID(),    																				item->getFlags());    				if (new_listener)    				{ -					itemp = createFolderViewItem(new_listener); +				folder_view_item = createFolderViewItem(new_listener);    				}    			} -  			if (itemp) -  			{ -  				itemp->addToFolder(parent_folder, mFolderRoot); -   			} -		} +  	    if (folder_view_item) +  		{ +            llassert(parent_folder != NULL); +            folder_view_item->addToFolder(parent_folder); +			addItemID(id, folder_view_item); +   		}  	}  	// If this is a folder, add the children of the folder and recursively add any   	// child folders. -	if (id.isNull() -		||	(objectp -			&& objectp->getType() == LLAssetType::AT_CATEGORY)) +	if (folder_view_item && objectp->getType() == LLAssetType::AT_CATEGORY)  	{  		LLViewerInventoryCategory::cat_array_t* categories;  		LLViewerInventoryItem::item_array_t* items; @@ -771,7 +803,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)  			}  		} -		if(items && parent_folder) +		if(items)  		{  			for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin();  				 item_iter != items->end(); @@ -784,7 +816,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)  		mInventory->unlockDirectDescendentArrays(id);  	} -	return itemp; +	return folder_view_item;  }  // bit of a hack to make sure the inventory is open. @@ -795,8 +827,8 @@ void LLInventoryPanel::openStartFolderOrMyInventory()  	{  		LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);  		if (fchild -			&& fchild->getListener() -				&& fchild->getListener()->getUUID() == gInventory.getRootFolderID()) +			&& fchild->getViewModelItem() +			&& fchild->getViewModelItem()->getName() == "My Inventory")  		{  			fchild->setOpen(TRUE);  			break; @@ -813,7 +845,7 @@ void LLInventoryPanel::openSelected()  {  	LLFolderViewItem* folder_item = mFolderRoot->getCurSelectedItem();  	if(!folder_item) return; -	LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); +	LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();  	if(!bridge) return;  	bridge->openItem();  } @@ -917,7 +949,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc  	{  		return;  	} -	mFolderRoot->setSelectionByID(obj_id, take_keyboard_focus); +	setSelectionByID(obj_id, take_keyboard_focus);  }  void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb)  @@ -930,7 +962,7 @@ void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::  void LLInventoryPanel::clearSelection()  { -	mFolderRoot->clearSelection(); +	mSelectThisID.setNull();  }  void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action) @@ -939,7 +971,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it  	mCompletionObserver->reset();  	for (std::deque<LLFolderViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it)  	{ -		LLUUID id = (*it)->getListener()->getUUID(); +		LLUUID id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID();  		LLViewerInventoryItem* inv_item = mInventory->getItem(id);  		if (inv_item && !inv_item->isFinished()) @@ -959,19 +991,15 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it  	}  } -void LLInventoryPanel::doToSelected(const LLSD& userdata) -{ -	mFolderRoot->doToSelected(&gInventory, userdata); -} -  void LLInventoryPanel::doCreate(const LLSD& userdata)  { -	menu_create_inventory_item(mFolderRoot, LLFolderBridge::sSelf.get(), userdata); +	reset_inventory_filter(); +	menu_create_inventory_item(this, LLFolderBridge::sSelf.get(), userdata);  }  bool LLInventoryPanel::beginIMSession()  { -	std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); +	std::set<LLFolderViewItem*> selected_items =   mFolderRoot->getSelectionList();  	std::string name;  	static int session_num = 1; @@ -979,20 +1007,19 @@ bool LLInventoryPanel::beginIMSession()  	LLDynamicArray<LLUUID> members;  	EInstantMessage type = IM_SESSION_CONFERENCE_START; -	std::set<LLUUID>::const_iterator iter; +	std::set<LLFolderViewItem*>::const_iterator iter;  	for (iter = selected_items.begin(); iter != selected_items.end(); iter++)  	{ -		LLUUID item = *iter; -		LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); +		LLFolderViewItem* folder_item = (*iter);  		if(folder_item)   		{ -			LLFolderViewEventListener* fve_listener = folder_item->getListener(); +			LLFolderViewModelItemInventory* fve_listener = static_cast<LLFolderViewModelItemInventory*>(folder_item->getViewModelItem());  			if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY))  			{ -				LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); +				LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getViewModelItem();  				if(!bridge) return true;  				LLViewerInventoryCategory* cat = bridge->getCategory();  				if(!cat) return true; @@ -1026,9 +1053,7 @@ bool LLInventoryPanel::beginIMSession()  			}  			else  			{ -				LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); -				if(!folder_item) return true; -				LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); +				LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getViewModelItem();  				if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)  				{ @@ -1069,13 +1094,13 @@ bool LLInventoryPanel::beginIMSession()  bool LLInventoryPanel::attachObject(const LLSD& userdata)  {  	// Copy selected item UUIDs to a vector. -	std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); +	std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList();  	uuid_vec_t items; -	for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin();  +	for (std::set<LLFolderViewItem*>::const_iterator set_iter = selected_items.begin();  		 set_iter != selected_items.end();   		 ++set_iter)  	{ -		items.push_back(*set_iter); +		items.push_back(static_cast<LLFolderViewModelItemInventory*>((*set_iter)->getViewModelItem())->getUUID());  	}  	// Attach selected items. @@ -1088,7 +1113,7 @@ bool LLInventoryPanel::attachObject(const LLSD& userdata)  BOOL LLInventoryPanel::getSinceLogoff()  { -	return getFilter()->isSinceLogoff(); +	return getFilter().isSinceLogoff();  }  // DEBUG ONLY @@ -1214,12 +1239,93 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L  void LLInventoryPanel::addHideFolderType(LLFolderType::EType folder_type)  { -	getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << folder_type)); +	getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << folder_type));  }  BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) const  { -	return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type)); +	return !(getFilter().getFilterCategoryTypes() & (1ULL << folder_type)); +} + +void LLInventoryPanel::addItemID( const LLUUID& id, LLFolderViewItem*   itemp ) +{ +	mItemMap[id] = itemp; +} + +void LLInventoryPanel::removeItemID(const LLUUID& id) +{ +	LLInventoryModel::cat_array_t categories; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(id, categories, items, TRUE); + +	mItemMap.erase(id); + +	for (LLInventoryModel::cat_array_t::iterator it = categories.begin(),    end_it = categories.end(); +		it != end_it; +		++it) +	{ +		mItemMap.erase((*it)->getUUID()); +} + +	for (LLInventoryModel::item_array_t::iterator it = items.begin(),   end_it  = items.end(); +		it != end_it; +		++it) +	{ +		mItemMap.erase((*it)->getUUID()); +	} +} + +LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); +LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) +{ +	LLFastTimer _(FTM_GET_ITEM_BY_ID); + +	std::map<LLUUID, LLFolderViewItem*>::iterator map_it; +	map_it = mItemMap.find(id); +	if (map_it != mItemMap.end()) +	{ +		return map_it->second; +	} + +	return NULL; +} + +LLFolderViewFolder* LLInventoryPanel::getFolderByID(const LLUUID& id) +{ +	LLFolderViewItem* item = getItemByID(id); +	return dynamic_cast<LLFolderViewFolder*>(item); +} + + +void LLInventoryPanel::setSelectionByID( const LLUUID& obj_id, BOOL    take_keyboard_focus ) +{ +	LLFolderViewItem* itemp = getItemByID(obj_id); +	if(itemp && itemp->getViewModelItem()) +	{ +		itemp->arrangeAndSet(TRUE, take_keyboard_focus); +		mSelectThisID.setNull(); +		return; +	} +	else +	{ +		// save the desired item to be selected later (if/when ready) +		mSelectThisID = obj_id; +	} +} + +void LLInventoryPanel::updateSelection() +{ +	if (mSelectThisID.notNull()) +	{ +		setSelectionByID(mSelectThisID, false); +	} +} + +void LLInventoryPanel::doToSelected(const LLSD& userdata) +{ +	LLInventoryAction::doToSelected(mInventory, mFolderRoot, userdata.asString()); + +	return;  } @@ -1240,7 +1346,7 @@ public:  	{  		LLInventoryPanel::initFromParams(p);  		// turn on inbox for recent items -		getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX)); +		getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX));  	}  protected: @@ -1255,3 +1361,34 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)  	mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;  } +namespace LLInitParam +{ +	void TypeValues<LLFolderType::EType>::declareValues() +	{ +		declare(LLFolderType::lookup(LLFolderType::FT_TEXTURE)          , LLFolderType::FT_TEXTURE); +		declare(LLFolderType::lookup(LLFolderType::FT_SOUND)            , LLFolderType::FT_SOUND); +		declare(LLFolderType::lookup(LLFolderType::FT_CALLINGCARD)      , LLFolderType::FT_CALLINGCARD); +		declare(LLFolderType::lookup(LLFolderType::FT_LANDMARK)         , LLFolderType::FT_LANDMARK); +		declare(LLFolderType::lookup(LLFolderType::FT_CLOTHING)         , LLFolderType::FT_CLOTHING); +		declare(LLFolderType::lookup(LLFolderType::FT_OBJECT)           , LLFolderType::FT_OBJECT); +		declare(LLFolderType::lookup(LLFolderType::FT_NOTECARD)         , LLFolderType::FT_NOTECARD); +		declare(LLFolderType::lookup(LLFolderType::FT_ROOT_INVENTORY)   , LLFolderType::FT_ROOT_INVENTORY); +		declare(LLFolderType::lookup(LLFolderType::FT_LSL_TEXT)         , LLFolderType::FT_LSL_TEXT); +		declare(LLFolderType::lookup(LLFolderType::FT_BODYPART)         , LLFolderType::FT_BODYPART); +		declare(LLFolderType::lookup(LLFolderType::FT_TRASH)            , LLFolderType::FT_TRASH); +		declare(LLFolderType::lookup(LLFolderType::FT_SNAPSHOT_CATEGORY), LLFolderType::FT_SNAPSHOT_CATEGORY); +		declare(LLFolderType::lookup(LLFolderType::FT_LOST_AND_FOUND)   , LLFolderType::FT_LOST_AND_FOUND); +		declare(LLFolderType::lookup(LLFolderType::FT_ANIMATION)        , LLFolderType::FT_ANIMATION); +		declare(LLFolderType::lookup(LLFolderType::FT_GESTURE)          , LLFolderType::FT_GESTURE); +		declare(LLFolderType::lookup(LLFolderType::FT_FAVORITE)         , LLFolderType::FT_FAVORITE); +		declare(LLFolderType::lookup(LLFolderType::FT_ENSEMBLE_START)   , LLFolderType::FT_ENSEMBLE_START); +		declare(LLFolderType::lookup(LLFolderType::FT_ENSEMBLE_END)     , LLFolderType::FT_ENSEMBLE_END); +		declare(LLFolderType::lookup(LLFolderType::FT_CURRENT_OUTFIT)   , LLFolderType::FT_CURRENT_OUTFIT); +		declare(LLFolderType::lookup(LLFolderType::FT_OUTFIT)           , LLFolderType::FT_OUTFIT); +		declare(LLFolderType::lookup(LLFolderType::FT_MY_OUTFITS)       , LLFolderType::FT_MY_OUTFITS); +		declare(LLFolderType::lookup(LLFolderType::FT_MESH )            , LLFolderType::FT_MESH ); +		declare(LLFolderType::lookup(LLFolderType::FT_INBOX)            , LLFolderType::FT_INBOX); +		declare(LLFolderType::lookup(LLFolderType::FT_OUTBOX)           , LLFolderType::FT_OUTBOX); +		declare(LLFolderType::lookup(LLFolderType::FT_BASIC_ROOT)       , LLFolderType::FT_BASIC_ROOT); +	} +} diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 6db59afb9b..c4f3c1b47d 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -30,6 +30,8 @@  #include "llassetstorage.h"  #include "lldarray.h" +#include "llfolderviewitem.h" +#include "llfolderviewmodelinventory.h"  #include "llfloater.h"  #include "llinventory.h"  #include "llinventoryfilter.h" @@ -38,22 +40,19 @@  #include "lluictrlfactory.h"  #include <set> -class LLFolderView; -class LLFolderViewFolder; -class LLFolderViewItem; -class LLInventoryFilter; -class LLInventoryModel;  class LLInvFVBridge; -class LLInventoryFVBridgeBuilder; -class LLMenuBarGL; -class LLCheckBoxCtrl; -class LLSpinCtrl; -class LLTextBox; -class LLIconCtrl; -class LLSaveFolderState; -class LLFilterEditor; -class LLTabContainer; +class LLInventoryFolderViewModelBuilder;  class LLInvPanelComplObserver; +class LLFolderViewModelInventory; + +namespace LLInitParam +{ +	template<> +	struct TypeValues<LLFolderType::EType> : public TypeValuesHelper<LLFolderType::EType> +	{ +		static void declareValues(); +	}; +}  class LLInventoryPanel : public LLPanel  { @@ -74,6 +73,19 @@ public:  		{}  	}; +	struct StartFolder : public LLInitParam::ChoiceBlock<StartFolder> +	{ +		Alternative<std::string>			name; +		Alternative<LLUUID>					id; +		Alternative<LLFolderType::EType>	type; + +		StartFolder() +		:	name("name"),  +			id("id"), +			type("type") +		{} +	}; +  	struct Params   	:	public LLInitParam::Block<Params, LLPanel::Params>  	{ @@ -82,12 +94,14 @@ public:  		Optional<bool>						allow_multi_select;  		Optional<bool>						show_item_link_overlays;  		Optional<Filter>					filter; -		Optional<std::string>               start_folder; +		Optional<StartFolder>               start_folder;  		Optional<bool>						use_label_suffix;  		Optional<bool>						show_empty_message; -		Optional<bool>						show_load_status;  		Optional<LLScrollContainer::Params>	scroll;  		Optional<bool>						accepts_drag_and_drop; +		Optional<LLFolderView::Params>		folder_view; +		Optional<LLFolderViewFolder::Params> folder; +		Optional<LLFolderViewItem::Params>	 item;  		Params()  		:	sort_order_setting("sort_order_setting"), @@ -98,24 +112,34 @@ public:  			start_folder("start_folder"),  			use_label_suffix("use_label_suffix", true),  			show_empty_message("show_empty_message", true), -			show_load_status("show_load_status"),  			scroll("scroll"), -			accepts_drag_and_drop("accepts_drag_and_drop") +			accepts_drag_and_drop("accepts_drag_and_drop"), +			folder_view("folder_view"), +			folder("folder"), +			item("item")  		{}  	}; +	struct InventoryState : public LLInitParam::Block<InventoryState> +	{ +		Mandatory<LLInventoryFilter::Params> filter; +		Mandatory<LLInventorySort::Params> sort; +	}; +  	//--------------------------------------------------------------------  	// Initialization  	//--------------------------------------------------------------------  protected:  	LLInventoryPanel(const Params&);  	void initFromParams(const Params&); +  	friend class LLUICtrlFactory;  public:  	virtual ~LLInventoryPanel();  public:  	LLInventoryModel* getModel() { return mInventory; } +	LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; }  	// LLView methods  	void draw(); @@ -137,8 +161,8 @@ public:  	void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);  	void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);  	void clearSelection(); -	LLInventoryFilter* getFilter(); -	const LLInventoryFilter* getFilter() const; +	LLInventoryFilter& getFilter(); +	const LLInventoryFilter& getFilter() const;  	void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT);  	U32 getFilterObjectTypes() const;  	void setFilterPermMask(PermissionMask filter_perm_mask); @@ -156,6 +180,7 @@ public:  	// This method is called when something has changed about the inventory.  	void modelChanged(U32 mask);  	LLFolderView* getRootFolder(); +	LLUUID getRootFolderID();  	LLScrollContainer* getScrollableContainer() { return mScroller; }  	void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); @@ -167,7 +192,8 @@ public:  	void doCreate(const LLSD& userdata);  	bool beginIMSession();  	bool attachObject(const LLSD& userdata); -	 +	static void idle(void* user_data); +  	// DEBUG ONLY:  	static void dumpSelectionInformation(void* user_data); @@ -182,30 +208,44 @@ public:  	static void openInventoryPanelAndSetSelection(BOOL auto_open, const LLUUID& obj_id); +	void addItemID(const LLUUID& id, LLFolderViewItem* itemp); +	void removeItemID(const LLUUID& id); +	LLFolderViewItem* getItemByID(const LLUUID& id); +	LLFolderViewFolder* getFolderByID(const LLUUID& id); +	void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); +	void updateSelection(); + +	LLFolderViewModelInventory* getFolderViewModel(); +	const LLFolderViewModelInventory* getFolderViewModel() const; +  protected:  	void openStartFolderOrMyInventory(); // open the first level of inventory  	void onItemsCompletion();			// called when selected items are complete +    LLUUID						mSelectThisID;	  	LLInventoryModel*			mInventory;  	LLInventoryObserver*		mInventoryObserver;  	LLInvPanelComplObserver*	mCompletionObserver; -	BOOL						mAcceptsDragAndDrop; -	BOOL 						mAllowMultiSelect; -	BOOL 						mShowItemLinkOverlays; // Shows link graphic over inventory item icons -	BOOL						mShowEmptyMessage; -	BOOL						mShowLoadStatus; +	bool						mAcceptsDragAndDrop; +	bool 						mAllowMultiSelect; +	bool 						mShowItemLinkOverlays; // Shows link graphic over inventory item icons +	bool						mShowEmptyMessage;  	LLFolderView*				mFolderRoot;  	LLScrollContainer*			mScroller; +	LLFolderViewModelInventory	mInventoryViewModel; +	Params						mParams;	// stored copy of parameter block + +	std::map<LLUUID, LLFolderViewItem*> mItemMap;  	/** -	 * Pointer to LLInventoryFVBridgeBuilder. +	 * Pointer to LLInventoryFolderViewModelBuilder.  	 *  	 * It is set in LLInventoryPanel's constructor and can be overridden in derived classes with   	 * another implementation.  	 * Take into account it will not be deleted by LLInventoryPanel itself.  	 */ -	const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder; +	const LLInventoryFolderViewModelBuilder* mInvFVBridgeBuilder;  	//-------------------------------------------------------------------- @@ -218,7 +258,6 @@ public:  	void setSortOrder(U32 order);  	U32 getSortOrder() const; -	void requestSort();  private:  	std::string					mSortOrderSetting; @@ -231,26 +270,20 @@ public:  	void addHideFolderType(LLFolderType::EType folder_type);  public: -	BOOL 				getIsViewsInitialized() const { return mViewsInitialized; } -	const LLUUID&		getRootFolderID() const; +	BOOL getIsViewsInitialized() const { return mViewsInitialized; }  protected:  	// Builds the UI.  Call this once the inventory is usable.  	void 				initializeViews(); -	LLFolderViewItem*	rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views. -	virtual void		buildFolderView(const LLInventoryPanel::Params& params);  	LLFolderViewItem*	buildNewViews(const LLUUID& id);  	BOOL				getIsHiddenFolderType(LLFolderType::EType folder_type) const; -	virtual LLFolderView*		createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix); +    virtual LLFolderView * createFolderRoot(LLUUID root_id );  	virtual LLFolderViewFolder*	createFolderViewFolder(LLInvFVBridge * bridge);  	virtual LLFolderViewItem*	createFolderViewItem(LLInvFVBridge * bridge);  private: -	BOOL				mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() -	BOOL				mViewsInitialized; // Views have been generated -	// UUID of category from which hierarchy should be built.  Set with the  -	// "start_folder" xml property.  Default is LLUUID::null that means total Inventory hierarchy.  -	LLUUID				mStartFolderID; +	bool				mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() +	bool				mViewsInitialized; // Views have been generated  };  #endif // LL_LLINVENTORYPANEL_H diff --git a/indra/newview/lllistcontextmenu.h b/indra/newview/lllistcontextmenu.h index fabd68ee20..04d3314829 100644 --- a/indra/newview/lllistcontextmenu.h +++ b/indra/newview/lllistcontextmenu.h @@ -37,7 +37,7 @@ class LLContextMenu;  /**   * Context menu for single or multiple list items.   *  - * Derived classes must implement contextMenu(). + * Derived classes must implement createMenu().   *    * Typical usage:   * <code> diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 10608463b4..362308c176 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1755,6 +1755,11 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,  		shader->bind();  	} +	if (shader) +	{ +		shader->bind(); +	} +  	//draw volume/plane intersections  	{  		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 4e28d1f526..472c26e22d 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -336,7 +336,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(  				// ...schedule a callback  				LLAvatarNameCache::get(id,  					boost::bind(&LLNameListCtrl::onAvatarNameCache, -						this, _1, _2)); +						this, _1, _2, item->getHandle()));  			}  			break;  		} @@ -392,7 +392,8 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)  }  void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, -									   const LLAvatarName& av_name) +									   const LLAvatarName& av_name, +									   LLHandle<LLNameListItem> item)  {  	std::string name;  	if (mShortNames) @@ -400,17 +401,14 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,  	else  		name = av_name.getCompleteName(); -	item_list::iterator iter; -	for (iter = getItemList().begin(); iter != getItemList().end(); iter++) +	LLNameListItem* list_item = item.get(); +	if (list_item && list_item->getUUID() == agent_id)  	{ -		LLScrollListItem* item = *iter; -		if (item->getUUID() == agent_id) +		LLScrollListCell* cell = list_item->getColumn(mNameColumnIndex); +		if (cell)  		{ -			LLScrollListCell* cell = item->getColumn(mNameColumnIndex); -			if (cell) -			{ -				cell->setValue(name); -			} +			cell->setValue(name); +			setNeedsSort();  		}  	} @@ -431,3 +429,8 @@ void LLNameListCtrl::updateColumns()  		}  	}  } + +void LLNameListCtrl::sortByName(BOOL ascending) +{ +	sortByColumnIndex(mNameColumnIndex,ascending); +} diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index ca9956dc53..ba85e77c65 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -33,6 +33,26 @@  class LLAvatarName; +/** + * LLNameListCtrl item + * + * We don't use LLScrollListItem to be able to override getUUID(), which is needed + * because the name list item value is not simply an UUID but a map (uuid, is_group). + */ +class LLNameListItem : public LLScrollListItem, public LLHandleProvider<LLNameListItem> +{ +public: +	LLUUID	getUUID() const		{ return getValue()["uuid"].asUUID(); } +protected: +	friend class LLNameListCtrl; + +	LLNameListItem( const LLScrollListItem::Params& p ) +	:	LLScrollListItem(p) +	{ +	} +}; + +  class LLNameListCtrl  :	public LLScrollListCtrl, public LLInstanceTracker<LLNameListCtrl>  { @@ -110,12 +130,14 @@ public:  	void setAllowCallingCardDrop(BOOL b) { mAllowCallingCardDrop = b; } +	void sortByName(BOOL ascending); +  	/*virtual*/ void updateColumns();  	/*virtual*/ void	mouseOverHighlightNthItem( S32 index );  private:  	void showInspector(const LLUUID& avatar_id, bool is_group); -	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); +	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, LLHandle<LLNameListItem> item);  private:  	S32    			mNameColumnIndex; @@ -124,24 +146,5 @@ private:  	bool			mShortNames;  // display name only, no SLID  }; -/** - * LLNameListCtrl item - * - * We don't use LLScrollListItem to be able to override getUUID(), which is needed - * because the name list item value is not simply an UUID but a map (uuid, is_group). - */ -class LLNameListItem : public LLScrollListItem -{ -public: -	LLUUID	getUUID() const		{ return getValue()["uuid"].asUUID(); } - -protected: -	friend class LLNameListCtrl; - -	LLNameListItem( const LLScrollListItem::Params& p ) -	:	LLScrollListItem(p) -	{ -	} -};  #endif diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a7303ad035..e1454fb5dc 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -1,8 +1,8 @@  /**    * @file LLNearbyChat.cpp - * @brief Nearby chat history scrolling panel implementation + * @brief LLNearbyChat class implementation   * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -26,68 +26,67 @@  #include "llviewerprecompiledheaders.h" -#include "llnearbychat.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" -#include "llrootview.h" -//#include "llchatitemscontainerctrl.h" +#include "message.h" +  #include "lliconctrl.h" +#include "llappviewer.h" +#include "llchatentry.h" +#include "llfloaterreg.h" +#include "lltrans.h" +#include "llimfloatercontainer.h"  #include "llfloatersidepanelcontainer.h"  #include "llfocusmgr.h"  #include "lllogchat.h"  #include "llresizebar.h"  #include "llresizehandle.h" +#include "lldraghandle.h"  #include "llmenugl.h" -#include "llviewermenu.h"//for gMenuHolder - +#include "llviewermenu.h" // for gMenuHolder  #include "llnearbychathandler.h"  #include "llchannelmanager.h" - -#include "llagent.h" 			// gAgent  #include "llchathistory.h"  #include "llstylemap.h" -  #include "llavatarnamecache.h" - -#include "lldraghandle.h" - -#include "llnearbychatbar.h"  #include "llfloaterreg.h"  #include "lltrans.h" -static const S32 RESIZE_BAR_THICKNESS = 3; - - -static LLRegisterPanelClassWrapper<LLNearbyChat> t_panel_nearby_chat("panel_nearby_chat"); +#include "llfirstuse.h" +#include "llnearbychat.h" +#include "llagent.h" // gAgent +#include "llgesturemgr.h" +#include "llmultigesture.h" +#include "llkeyboard.h" +#include "llanimationstates.h" +#include "llviewerstats.h" +#include "llcommandhandler.h" +#include "llviewercontrol.h" +#include "llnavigationbar.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llrootview.h" +#include "llviewerchat.h" +#include "lltranslate.h" -LLNearbyChat::LLNearbyChat(const LLNearbyChat::Params& p)  -:	LLPanel(p), -	mChatHistory(NULL) -{ -} +S32 LLNearbyChat::sLastSpecialChatChannel = 0; -BOOL LLNearbyChat::postBuild() +// --- 2 functions in the global namespace :( --- +bool isWordsName(const std::string& name)  { -	//menu -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - -	enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); -	registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); - -	 -	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(menu) -		mPopupMenuHandle = menu->getHandle(); - -	gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true); - -	mChatHistory = getChild<LLChatHistory>("chat_history"); +	// checking to see if it's display name plus username in parentheses +	S32 open_paren = name.find(" (", 0); +	S32 close_paren = name.find(')', 0); -	if(!LLPanel::postBuild()) -		return false; -	 -	return true; +	if (open_paren != std::string::npos && +		close_paren == name.length()-1) +	{ +		return true; +	} +	else +	{ +		//checking for a single space +		S32 pos = name.find(' ', 0); +		return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; +	}  }  std::string appendTime() @@ -106,52 +105,93 @@ std::string appendTime()  } -void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +const S32 EXPANDED_HEIGHT = 266; +const S32 COLLAPSED_HEIGHT = 60; +const S32 EXPANDED_MIN_HEIGHT = 150; + +// legacy callback glue +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); + +struct LLChatTypeTrigger { +	std::string name; +	EChatType type; +}; + +static LLChatTypeTrigger sChatTypeTriggers[] = { +	{ "/whisper"	, CHAT_TYPE_WHISPER}, +	{ "/shout"	, CHAT_TYPE_SHOUT} +}; + + +LLNearbyChat::LLNearbyChat(const LLSD& key) +:	LLIMConversation(key), +	//mOutputMonitor(NULL), +	mSpeakerMgr(NULL), +	mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT)  { -	LLChat& tmp_chat = const_cast<LLChat&>(chat); +	mIsNearbyChat = true; +	setIsChrome(TRUE); +	mKey = LLSD(); +	mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); +} -	if(tmp_chat.mTimeStr.empty()) -		tmp_chat.mTimeStr = appendTime(); +//virtual +BOOL LLNearbyChat::postBuild() +{ +    BOOL result = LLIMConversation::postBuild(); +	mInputEditor->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); +	mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); +	mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); +	mInputEditor->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); -	bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory"); -	 -	if (!chat.mMuted) -	{ -		tmp_chat.mFromName = chat.mFromName; -		LLSD chat_args = args; -		chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; -		mChatHistory->appendMessage(chat, chat_args); -	} +//	mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); +//	mOutputMonitor->setVisible(FALSE); -	if(archive) -	{ -		mMessageArchive.push_back(chat); -		if(mMessageArchive.size()>200) -			mMessageArchive.erase(mMessageArchive.begin()); -	} +	// Register for font change notifications +	LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChat::onChatFontChange, this, _1)); + +	// title must be defined BEFORE call addConversationListItem() because +	// it is used for show the item's name in the conversations list +	setTitle(LLTrans::getString("NearbyChatTitle")); + +	addToHost(); + +	//for menu +	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + +	enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); +	registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); -	if (args["do_not_log"].asBoolean())  +	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +	if(menu)  	{ -		return; +		mPopupMenuHandle = menu->getHandle();  	} -	if (gSavedPerAccountSettings.getBOOL("LogNearbyChat")) +	// obsolete, but may be needed for backward compatibility? +	gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); + +	if (gSavedPerAccountSettings.getBOOL("LogShowHistory"))  	{ -		std::string from_name = chat.mFromName; +		loadHistory(); +	} -		if (chat.mSourceType == CHAT_SOURCE_AGENT) -		{ -			// if the chat is coming from an agent, log the complete name -			LLAvatarName av_name; -			LLAvatarNameCache::get(chat.mFromID, &av_name); +	return result; +} -			if (!av_name.mIsDisplayNameDefault) -			{ -				from_name = av_name.getCompleteName(); -			} -		} +// virtual +void LLNearbyChat::refresh() +{ +	displaySpeakingIndicator(); +	updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); -		LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); +	// *HACK: Update transparency type depending on whether our children have focus. +	// This is needed because this floater is chrome and thus cannot accept focus, so +	// the transparency type setting code from LLFloater::setFocus() isn't reached. +	if (getTransparencyType() != TT_DEFAULT) +	{ +		setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE);  	}  } @@ -162,44 +202,47 @@ void LLNearbyChat::onNearbySpeakers()  	LLFloaterSidePanelContainer::showPanel("people", "panel_people", param);  } -  void	LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata)  {  } +  bool	LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)  {  	std::string str = userdata.asString();  	if(str == "nearby_people") -		onNearbySpeakers();	 +		onNearbySpeakers();  	return false;  } -void LLNearbyChat::removeScreenChat() +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusReceived()  { -	LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); -	if(chat_channel) -	{ -		chat_channel->removeToastsFromChannel(); -	} +	setBackgroundOpaque(true); +	LLIMConversation::onFocusReceived();  } -void	LLNearbyChat::setVisible(BOOL visible) +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusLost()  { -	if(visible) -	{ -		removeScreenChat(); -	} - -	LLPanel::setVisible(visible); +	setBackgroundOpaque(false); +	LLIMConversation::onFocusLost();  } - -void LLNearbyChat::getAllowedRect(LLRect& rect) +BOOL	LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask)  { -	rect = gViewerWindow->getWorldViewRectScaled(); +	//fix for EXT-6625 +	//highlight NearbyChat history whenever mouseclick happen in NearbyChat +	//setting focus to eidtor will force onFocusLost() call that in its turn will change +	//background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. + +	if(mChatHistory) +		mChatHistory->setFocus(TRUE); +	return LLPanel::handleMouseDown(x, y, mask);  } -void LLNearbyChat::updateChatHistoryStyle() +void LLNearbyChat::reloadMessages()  {  	mChatHistory->clear(); @@ -212,34 +255,6 @@ void LLNearbyChat::updateChatHistoryStyle()  	}  } -//static  -void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue) -{ -	LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); -	LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); -	if(nearby_chat) -		nearby_chat->updateChatHistoryStyle(); -} - -bool isWordsName(const std::string& name) -{ -	// checking to see if it's display name plus username in parentheses  -	S32 open_paren = name.find(" (", 0); -	S32 close_paren = name.find(')', 0); - -	if (open_paren != std::string::npos && -		close_paren == name.length()-1) -	{ -		return true; -	} -	else -	{ -		//checking for a single space -		S32 pos = name.find(' ', 0); -		return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; -	} -} -  void LLNearbyChat::loadHistory()  {  	LLSD do_not_log; @@ -274,9 +289,9 @@ void LLNearbyChat::loadHistory()  		chat.mSourceType = CHAT_SOURCE_AGENT;  		if (from_id.isNull() && SYSTEM_FROM == from) -		{	 +		{  			chat.mSourceType = CHAT_SOURCE_SYSTEM; -			 +  		}  		else if (from_id.isNull())  		{ @@ -289,50 +304,620 @@ void LLNearbyChat::loadHistory()  	}  } +void LLNearbyChat::removeScreenChat() +{ +	LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); +	if(chat_channel) +	{ +		chat_channel->removeToastsFromChannel(); +	} +} + +void	LLNearbyChat::setVisible(BOOL visible) +{ +	if(visible) +	{ +		removeScreenChat(); +	} + +	LLIMConversation::setVisible(visible); +} + + +void LLNearbyChat::enableDisableCallBtn() +{ +	// bool btn_enabled = LLAgent::isActionAllowed("speak"); + +	getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); +} + +void LLNearbyChat::onTearOffClicked() +{ +	LLIMConversation::onTearOffClicked(); + +	// see CHUI-170: Save torn-off state of the nearby chat between sessions +	BOOL in_the_multifloater = !isTornOff(); +	gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); +} + +void LLNearbyChat::addToHost() +{ +	if ( LLIMConversation::isChatMultiTab()) +	{ +		LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); +		if (im_box) +		{ +			if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) +			{ +				im_box->addFloater(this, TRUE, LLTabContainer::END); +			} +			else +			{ +				// setting of the "potential" host: this sequence sets +				// LLFloater::mHostHandle = NULL (a current host), but +				// LLFloater::mLastHostHandle = im_box (a "future" host) +				setHost(im_box); +				setHost(NULL); +			} +		} +	} +} + +// virtual +void LLNearbyChat::onOpen(const LLSD& key) +{ +	LLIMConversation::onOpen(key); +	showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +} + +void LLNearbyChat::onChatFontChange(LLFontGL* fontp) +{ +	// Update things with the new font whohoo +	if (mInputEditor) +	{ +		mInputEditor->setFont(fontp); +	} +} +  //static  LLNearbyChat* LLNearbyChat::getInstance()  { -	LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); -	return chat_bar->findChild<LLNearbyChat>("nearby_chat"); +	return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar", LLSD(LLUUID::null));  } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusReceived() +void LLNearbyChat::show()  { -	setBackgroundOpaque(true); -	LLPanel::onFocusReceived(); +	if (isChatMultiTab()) +	{ +		openFloater(getKey()); +	}  } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusLost() +bool LLNearbyChat::isChatVisible() const  { -	setBackgroundOpaque(false); -	LLPanel::onFocusLost(); +	bool isVisible = false; +	LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); +	// Is the IM floater container ever null? +	llassert(im_box != NULL); +	if (im_box != NULL) +	{ +		isVisible = +				isChatMultiTab() && gSavedSettings.getBOOL("NearbyChatIsNotTornOff")? +						im_box->getVisible() && !im_box->isMinimized() : +						getVisible() && !isMinimized(); +	} + +	return isVisible;  } -BOOL	LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) +void LLNearbyChat::showHistory()  { -	//fix for EXT-6625 -	//highlight NearbyChat history whenever mouseclick happen in NearbyChat -	//setting focus to eidtor will force onFocusLost() call that in its turn will change  -	//background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. +	openFloater(); +	setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); +} + +std::string LLNearbyChat::getCurrentChat() +{ +	return mInputEditor ? mInputEditor->getText() : LLStringUtil::null; +} + +// virtual +BOOL LLNearbyChat::handleKeyHere( KEY key, MASK mask ) +{ +	BOOL handled = FALSE; + +	if( KEY_RETURN == key && mask == MASK_CONTROL) +	{ +		// shout +		sendChat(CHAT_TYPE_SHOUT); +		handled = TRUE; +	} + +	return handled; +} + +BOOL LLNearbyChat::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) +{ +	U32 in_len = in_str.length(); +	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); -	if(mChatHistory) -		mChatHistory->setFocus(TRUE); -	return LLPanel::handleMouseDown(x, y, mask); +	bool string_was_found = false; + +	for (S32 n = 0; n < cnt && !string_was_found; n++) +	{ +		if (in_len <= sChatTypeTriggers[n].name.length()) +		{ +			std::string trigger_trunc = sChatTypeTriggers[n].name; +			LLStringUtil::truncate(trigger_trunc, in_len); + +			if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) +			{ +				*out_str = sChatTypeTriggers[n].name; +				string_was_found = true; +			} +		} +	} + +	return string_was_found;  } -void LLNearbyChat::draw() +void LLNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userdata)  { -	// *HACK: Update transparency type depending on whether our children have focus. -	// This is needed because this floater is chrome and thus cannot accept focus, so -	// the transparency type setting code from LLFloater::setFocus() isn't reached. -	if (getTransparencyType() != TT_DEFAULT) +	LLFirstUse::otherAvatarChatFirst(false); + +	LLNearbyChat* self = (LLNearbyChat *)userdata; + +	LLWString raw_text = self->mInputEditor->getWText(); + +	// Can't trim the end, because that will cause autocompletion +	// to eat trailing spaces that might be part of a gesture. +	LLWStringUtil::trimHead(raw_text); + +	S32 length = raw_text.length(); + +	if( (length > 0) && (raw_text[0] != '/') )  // forward slash is used for escape (eg. emote) sequences  	{ -		setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); +		gAgent.startTyping(); +	} +	else +	{ +		gAgent.stopTyping(); +	} + +	/* Doesn't work -- can't tell the difference between a backspace +	   that killed the selection vs. backspace at the end of line. +	if (length > 1  +		&& text[0] == '/' +		&& key == KEY_BACKSPACE) +	{ +		// the selection will already be deleted, but we need to trim +		// off the character before +		std::string new_text = raw_text.substr(0, length-1); +		self->mInputEditor->setText( new_text ); +		self->mInputEditor->setCursorToEnd(); +		length = length - 1; +	} +	*/ + +	KEY key = gKeyboard->currentKey(); + +	// Ignore "special" keys, like backspace, arrows, etc. +	if (length > 1  +		&& raw_text[0] == '/' +		&& key < KEY_SPECIAL) +	{ +		// we're starting a gesture, attempt to autocomplete + +		std::string utf8_trigger = wstring_to_utf8str(raw_text); +		std::string utf8_out_str(utf8_trigger); + +		if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) +		{ +			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); +			self->mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part + +			// Select to end of line, starting from the character +			// after the last one the user typed. +			self->mInputEditor->selectNext(rest_of_match, false); +		} +		else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) +		{ +			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); +			self->mInputEditor->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part +			self->mInputEditor->endOfDoc(); +		} + +		//llinfos << "GESTUREDEBUG " << trigger  +		//	<< " len " << length +		//	<< " outlen " << out_str.getLength() +		//	<< llendl; +	} +} + +// static +void LLNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) +{ +	// stop typing animation +	gAgent.stopTyping(); +} + +void LLNearbyChat::onChatBoxFocusReceived() +{ +	mInputEditor->setEnabled(!gDisconnected); +} + +EChatType LLNearbyChat::processChatTypeTriggers(EChatType type, std::string &str) +{ +	U32 length = str.length(); +	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); +	 +	for (S32 n = 0; n < cnt; n++) +	{ +		if (length >= sChatTypeTriggers[n].name.length()) +		{ +			std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); + +			if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) +			{ +				U32 trigger_length = sChatTypeTriggers[n].name.length(); + +				// It's to remove space after trigger name +				if (length > trigger_length && str[trigger_length] == ' ') +					trigger_length++; + +				str = str.substr(trigger_length, length); + +				if (CHAT_TYPE_NORMAL == type) +					return sChatTypeTriggers[n].type; +				else +					break; +			} +		} +	} + +	return type; +} + +void LLNearbyChat::sendChat( EChatType type ) +{ +	if (mInputEditor) +	{ +		LLWString text = mInputEditor->getWText(); +		LLWStringUtil::trim(text); +		LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. +		if (!text.empty()) +		{ +			// Check if this is destined for another channel +			S32 channel = 0; +			stripChannelNumber(text, &channel); +			 +			std::string utf8text = wstring_to_utf8str(text); +			// Try to trigger a gesture, if not chat to a script. +			std::string utf8_revised_text; +			if (0 == channel) +			{ +				// discard returned "found" boolean +				LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); +			} +			else +			{ +				utf8_revised_text = utf8text; +			} + +			utf8_revised_text = utf8str_trim(utf8_revised_text); + +			type = processChatTypeTriggers(type, utf8_revised_text); + +			if (!utf8_revised_text.empty()) +			{ +				// Chat with animation +				sendChatFromViewer(utf8_revised_text, type, TRUE); +			} +		} + +		mInputEditor->setText(LLStringExplicit("")); +	} + +	gAgent.stopTyping(); + +	// If the user wants to stop chatting on hitting return, lose focus +	// and go out of chat mode. +	if (gSavedSettings.getBOOL("CloseChatOnReturn")) +	{ +		stopChat();  	} +} + + +void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) +{ +	LLChat& tmp_chat = const_cast<LLChat&>(chat); + +	if(tmp_chat.mTimeStr.empty()) +		tmp_chat.mTimeStr = appendTime(); + +	if (!chat.mMuted) +	{ +		tmp_chat.mFromName = chat.mFromName; +		LLSD chat_args; +		if (args) chat_args = args; +		chat_args["use_plain_text_chat_history"] = +				gSavedSettings.getBOOL("PlainTextChatHistory"); +		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); +		chat_args["show_names_for_p2p_conv"] = true; -	LLPanel::draw(); +		mChatHistory->appendMessage(chat, chat_args); +	}  } + +void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +{ +	appendMessage(chat, args); + +	if(archive) +	{ +		mMessageArchive.push_back(chat); +		if(mMessageArchive.size()>200) +			mMessageArchive.erase(mMessageArchive.begin()); +	} + +	// logging +	if (!args["do_not_log"].asBoolean() +			&& gSavedPerAccountSettings.getBOOL("LogNearbyChat")) +	{ +		std::string from_name = chat.mFromName; + +		if (chat.mSourceType == CHAT_SOURCE_AGENT) +		{ +			// if the chat is coming from an agent, log the complete name +			LLAvatarName av_name; +			LLAvatarNameCache::get(chat.mFromID, &av_name); + +			if (!av_name.mIsDisplayNameDefault) +			{ +				from_name = av_name.getCompleteName(); +			} +		} + +		LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); +	} +} + + +void LLNearbyChat::onChatBoxCommit() +{ +	if (mInputEditor->getText().length() > 0) +	{ +		sendChat(CHAT_TYPE_NORMAL); +	} + +	gAgent.stopTyping(); +} + +void LLNearbyChat::displaySpeakingIndicator() +{ +	LLSpeakerMgr::speaker_list_t speaker_list; +	LLUUID id; + +	id.setNull(); +	mSpeakerMgr->update(TRUE); +	mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); + +	for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) +	{ +		LLPointer<LLSpeaker> s = *i; +		if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) +		{ +			id = s->mID; +			break; +		} +	} + +	if (!id.isNull()) +	{ +		//mOutputMonitor->setVisible(TRUE); +		//mOutputMonitor->setSpeakerId(id); +	} +	else +	{ +		//mOutputMonitor->setVisible(FALSE); +	} +} + +void LLNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) +{ +	sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); +} + +void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) +{ +	// Look for "/20 foo" channel chats. +	S32 channel = 0; +	LLWString out_text = stripChannelNumber(wtext, &channel); +	std::string utf8_out_text = wstring_to_utf8str(out_text); +	std::string utf8_text = wstring_to_utf8str(wtext); + +	utf8_text = utf8str_trim(utf8_text); +	if (!utf8_text.empty()) +	{ +		utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); +	} + +	// Don't animate for chats people can't hear (chat to scripts) +	if (animate && (channel == 0)) +	{ +		if (type == CHAT_TYPE_WHISPER) +		{ +			lldebugs << "You whisper " << utf8_text << llendl; +			gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); +		} +		else if (type == CHAT_TYPE_NORMAL) +		{ +			lldebugs << "You say " << utf8_text << llendl; +			gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); +		} +		else if (type == CHAT_TYPE_SHOUT) +		{ +			lldebugs << "You shout " << utf8_text << llendl; +			gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); +		} +		else +		{ +			llinfos << "send_chat_from_viewer() - invalid volume" << llendl; +			return; +		} +	} +	else +	{ +		if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) +		{ +			lldebugs << "Channel chat: " << utf8_text << llendl; +		} +	} + +	send_chat_from_viewer(utf8_out_text, type, channel); +} + +// static  +void LLNearbyChat::startChat(const char* line) +{ +	LLNearbyChat* cb = LLNearbyChat::getInstance(); + +	if (cb ) +	{ +		cb->show(); +		cb->setVisible(TRUE); +		cb->setFocus(TRUE); +		cb->mInputEditor->setFocus(TRUE); + +		if (line) +		{ +			std::string line_string(line); +			cb->mInputEditor->setText(line_string); +		} + +		cb->mInputEditor->endOfDoc(); +	} +} + +// Exit "chat mode" and do the appropriate focus changes +// static +void LLNearbyChat::stopChat() +{ +	LLNearbyChat* cb = LLNearbyChat::getInstance(); + +	if (cb) +	{ +		cb->mInputEditor->setFocus(FALSE); + +		// stop typing animation +		gAgent.stopTyping(); +	} +} + +// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. +// Otherwise returns input and channel 0. +LLWString LLNearbyChat::stripChannelNumber(const LLWString &mesg, S32* channel) +{ +	if (mesg[0] == '/' +		&& mesg[1] == '/') +	{ +		// This is a "repeat channel send" +		*channel = sLastSpecialChatChannel; +		return mesg.substr(2, mesg.length() - 2); +	} +	else if (mesg[0] == '/' +			 && mesg[1] +			 && LLStringOps::isDigit(mesg[1])) +	{ +		// This a special "/20" speak on a channel +		S32 pos = 0; + +		// Copy the channel number into a string +		LLWString channel_string; +		llwchar c; +		do +		{ +			c = mesg[pos+1]; +			channel_string.push_back(c); +			pos++; +		} +		while(c && pos < 64 && LLStringOps::isDigit(c)); +		 +		// Move the pointer forward to the first non-whitespace char +		// Check isspace before looping, so we can handle "/33foo" +		// as well as "/33 foo" +		while(c && iswspace(c)) +		{ +			c = mesg[pos+1]; +			pos++; +		} +		 +		sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); +		*channel = sLastSpecialChatChannel; +		return mesg.substr(pos, mesg.length() - pos); +	} +	else +	{ +		// This is normal chat. +		*channel = 0; +		return mesg; +	} +} + +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) +{ +	LLMessageSystem* msg = gMessageSystem; +	msg->newMessageFast(_PREHASH_ChatFromViewer); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); +	msg->nextBlockFast(_PREHASH_ChatData); +	msg->addStringFast(_PREHASH_Message, utf8_out_text); +	msg->addU8Fast(_PREHASH_Type, type); +	msg->addS32("Channel", channel); + +	gAgent.sendReliableMessage(); + +	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); +} + +class LLChatCommandHandler : public LLCommandHandler +{ +public: +	// not allowed from outside the app +	LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } + +    // Your code here +	bool handle(const LLSD& tokens, const LLSD& query_map, +				LLMediaCtrl* web) +	{ +		bool retval = false; +		// Need at least 2 tokens to have a valid message. +		if (tokens.size() < 2) +		{ +			retval = false; +		} +		else +		{ +		S32 channel = tokens[0].asInteger(); +			// VWR-19499 Restrict function to chat channels greater than 0. +			if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) +			{ +				retval = true; +		// Send unescaped message, see EXT-6353. +		std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); +		send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); +			} +			else +			{ +				retval = false; +				// Tell us this is an unsupported SLurl. +			} +		} +		return retval; +	} +}; + +// Creating the object registers with the dispatcher. +LLChatCommandHandler gChatHandler; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 7c5975cbc5..7c58e3037e 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -1,8 +1,8 @@ - /**  +/**    * @file llnearbychat.h - * @brief nearby chat history scrolling panel implementation + * @brief LLNearbyChat class definition   * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -24,60 +24,108 @@   * $/LicenseInfo$   */ -#ifndef LL_LLNEARBYCHAT_H_ -#define LL_LLNEARBYCHAT_H_ +#ifndef LL_LLNEARBYCHAT_H +#define LL_LLNEARBYCHAT_H +#include "llimconversation.h" +#include "llcombobox.h" +#include "llgesturemgr.h" +#include "llchat.h" +#include "llvoiceclient.h" +#include "lloutputmonitorctrl.h" +#include "llspeakers.h"  #include "llscrollbar.h"  #include "llviewerchat.h" -#include "llfloater.h" +#include "llpanel.h"  class LLResizeBar; -class LLChatHistory; -class LLNearbyChat: public LLPanel +class LLNearbyChat +	:	public LLIMConversation  {  public: -	LLNearbyChat(const Params& p = LLPanel::getDefaultParams()); +	// constructor for inline chat-bars (e.g. hosted in chat history window) +	LLNearbyChat(const LLSD& key); +	~LLNearbyChat() {} -	BOOL	postBuild			(); +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); + +	// focus overrides +	/*virtual*/ void	onFocusLost(); +	/*virtual*/ void	onFocusReceived(); + +	/*virtual*/ void	setVisible(BOOL visible); + +	void loadHistory(); +    void reloadMessages(); +	void removeScreenChat(); + +	static LLNearbyChat* getInstance(); + +	void addToHost(); +	void show(); +	bool isChatVisible() const;  	/** @param archive true - to save a message to the chat history log */ -	void	addMessage			(const LLChat& message,bool archive = true, const LLSD &args = LLSD());	 +	void	addMessage			(const LLChat& message,bool archive = true, const LLSD &args = LLSD());  	void	onNearbyChatContextMenuItemClicked(const LLSD& userdata);  	bool	onNearbyChatCheckContextMenuItem(const LLSD& userdata); +	LLChatEntry* getChatBox() { return mInputEditor; } + +	std::string getCurrentChat(); + +	virtual BOOL handleKeyHere( KEY key, MASK mask );  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask); -	virtual void	draw(); -	// focus overrides -	/*virtual*/ void	onFocusLost(); -	/*virtual*/ void	onFocusReceived(); -	 -	/*virtual*/ void	setVisible(BOOL visible); -	 -	virtual void updateChatHistoryStyle(); +	static void startChat(const char* line); +	static void stopChat(); -	static void processChatHistoryStyleUpdate(const LLSD& newvalue); +	static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); +	static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); -	void loadHistory(); +	void showHistory(); -	static LLNearbyChat* getInstance(); -	void removeScreenChat(); +protected: +	static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); +	static void onChatBoxKeystroke(LLTextEditor* caller, void* userdata); +	static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); +	void onChatBoxFocusReceived(); -private: +	void sendChat( EChatType type ); +	void onChatBoxCommit(); +	void onChatFontChange(LLFontGL* fontp); -	void	getAllowedRect		(LLRect& rect); +	/*virtual*/ void onTearOffClicked(); -	void	onNearbySpeakers	(); +	static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); +	EChatType processChatTypeTriggers(EChatType type, std::string &str); + +	void displaySpeakingIndicator(); + +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn(); + +	// Which non-zero channel did we last chat on? +	static S32 sLastSpecialChatChannel; + +	LLOutputMonitorCtrl*	mOutputMonitor; +	LLLocalSpeakerMgr*		mSpeakerMgr; +	S32 mExpandedHeight;  private: -	LLHandle<LLView>	mPopupMenuHandle; -	LLChatHistory*		mChatHistory; +	// prepare chat's params and out one message to chatHistory +	void appendMessage(const LLChat& chat, const LLSD &args = 0); +	void	onNearbySpeakers	(); + +	/*virtual*/ void refresh(); + +	LLHandle<LLView>	mPopupMenuHandle;  	std::vector<LLChat> mMessageArchive; +  };  #endif - - diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp deleted file mode 100644 index f8f0f7d243..0000000000 --- a/indra/newview/llnearbychatbar.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/**  - * @file llnearbychatbar.cpp - * @brief LLNearbyChatBar class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "message.h" - -#include "llappviewer.h" -#include "llfloaterreg.h" -#include "lltrans.h" - -#include "llfirstuse.h" -#include "llnearbychatbar.h" -#include "llnearbychatbarlistener.h" -#include "llagent.h" -#include "llgesturemgr.h" -#include "llmultigesture.h" -#include "llkeyboard.h" -#include "llanimationstates.h" -#include "llviewerstats.h" -#include "llcommandhandler.h" -#include "llviewercontrol.h" -#include "llnavigationbar.h" -#include "llwindow.h" -#include "llviewerwindow.h" -#include "llrootview.h" -#include "llviewerchat.h" -#include "llnearbychat.h" -#include "lltranslate.h" - -#include "llresizehandle.h" -#include "llautoreplace.h" - -S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; - -const S32 EXPANDED_HEIGHT = 300; -const S32 COLLAPSED_HEIGHT = 60; -const S32 EXPANDED_MIN_HEIGHT = 150; - -// legacy callback glue -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); - -struct LLChatTypeTrigger { -	std::string name; -	EChatType type; -}; - -static LLChatTypeTrigger sChatTypeTriggers[] = { -	{ "/whisper"	, CHAT_TYPE_WHISPER}, -	{ "/shout"	, CHAT_TYPE_SHOUT} -}; - -LLNearbyChatBar::LLNearbyChatBar(const LLSD& key) -:	LLFloater(key), -	mChatBox(NULL), -	mNearbyChat(NULL), -	mOutputMonitor(NULL), -	mSpeakerMgr(NULL), -	mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) -{ -	mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); -	mListener.reset(new LLNearbyChatBarListener(*this)); -} - -//virtual -BOOL LLNearbyChatBar::postBuild() -{ -	mChatBox = getChild<LLLineEditor>("chat_box"); - -	mChatBox->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); -	mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this)); -	mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); -	mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); -	mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChatBar::onChatBoxFocusReceived, this)); - -	mChatBox->setIgnoreArrowKeys( FALSE );  -	mChatBox->setCommitOnFocusLost( FALSE ); -	mChatBox->setRevertOnEsc( FALSE ); -	mChatBox->setIgnoreTab(TRUE); -	mChatBox->setPassDelete(TRUE); -	mChatBox->setReplaceNewlinesWithSpaces(FALSE); -	mChatBox->setEnableLineHistory(TRUE); -	mChatBox->setFont(LLViewerChat::getChatFont()); - -	mNearbyChat = getChildView("nearby_chat"); - -	gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE); -	BOOL show_nearby_chat = gSavedSettings.getBOOL("nearbychat_history_visibility"); - -	LLButton* show_btn = getChild<LLButton>("show_nearby_chat"); -	show_btn->setCommitCallback(boost::bind(&LLNearbyChatBar::onToggleNearbyChatPanel, this)); -	show_btn->setToggleState(show_nearby_chat); - -	mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); -	mOutputMonitor->setVisible(FALSE); - -	showNearbyChatPanel(show_nearby_chat); - -	// Register for font change notifications -	LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); - -	enableResizeCtrls(true, true, false); - -	return TRUE; -} - -// virtual -void LLNearbyChatBar::onOpen(const LLSD& key) -{ -	showTranslationCheckbox(LLTranslate::isTranslationConfigured()); -} - -bool LLNearbyChatBar::applyRectControl() -{ -	bool rect_controlled = LLFloater::applyRectControl(); - -	if (!mNearbyChat->getVisible()) -	{ -		reshape(getRect().getWidth(), getMinHeight()); -		enableResizeCtrls(true, true, false); -	} -	else -	{ -		enableResizeCtrls(true); -		setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); -	} -	 -	return rect_controlled; -} - -void LLNearbyChatBar::onChatFontChange(LLFontGL* fontp) -{ -	// Update things with the new font whohoo -	if (mChatBox) -	{ -		mChatBox->setFont(fontp); -	} -} - -//static -LLNearbyChatBar* LLNearbyChatBar::getInstance() -{ -	return LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar"); -} - -void LLNearbyChatBar::showHistory() -{ -	openFloater(); - -	if (!getChildView("nearby_chat")->getVisible()) -	{ -		onToggleNearbyChatPanel(); -	} -} - -void LLNearbyChatBar::showTranslationCheckbox(BOOL show) -{ -	getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show); -} - -void LLNearbyChatBar::draw() -{ -	displaySpeakingIndicator(); -	LLFloater::draw(); -} - -std::string LLNearbyChatBar::getCurrentChat() -{ -	return mChatBox ? mChatBox->getText() : LLStringUtil::null; -} - -// virtual -BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask ) -{ -	BOOL handled = FALSE; - -	if( KEY_RETURN == key && mask == MASK_CONTROL) -	{ -		// shout -		sendChat(CHAT_TYPE_SHOUT); -		handled = TRUE; -	} - -	return handled; -} - -BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) -{ -	U32 in_len = in_str.length(); -	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); -	 -	for (S32 n = 0; n < cnt; n++) -	{ -		if (in_len > sChatTypeTriggers[n].name.length()) -			continue; - -		std::string trigger_trunc = sChatTypeTriggers[n].name; -		LLStringUtil::truncate(trigger_trunc, in_len); - -		if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) -		{ -			*out_str = sChatTypeTriggers[n].name; -			return TRUE; -		} -	} - -	return FALSE; -} - -void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) -{ -	LLFirstUse::otherAvatarChatFirst(false); - -	LLNearbyChatBar* self = (LLNearbyChatBar *)userdata; - -	LLWString raw_text = self->mChatBox->getWText(); - -	// Can't trim the end, because that will cause autocompletion -	// to eat trailing spaces that might be part of a gesture. -	LLWStringUtil::trimHead(raw_text); - -	S32 length = raw_text.length(); - -	if( (length > 0) && (raw_text[0] != '/') )  // forward slash is used for escape (eg. emote) sequences -	{ -		gAgent.startTyping(); -	} -	else -	{ -		gAgent.stopTyping(); -	} - -	/* Doesn't work -- can't tell the difference between a backspace -	   that killed the selection vs. backspace at the end of line. -	if (length > 1  -		&& text[0] == '/' -		&& key == KEY_BACKSPACE) -	{ -		// the selection will already be deleted, but we need to trim -		// off the character before -		std::string new_text = raw_text.substr(0, length-1); -		self->mInputEditor->setText( new_text ); -		self->mInputEditor->setCursorToEnd(); -		length = length - 1; -	} -	*/ - -	KEY key = gKeyboard->currentKey(); - -	// Ignore "special" keys, like backspace, arrows, etc. -	if (length > 1  -		&& raw_text[0] == '/' -		&& key < KEY_SPECIAL) -	{ -		// we're starting a gesture, attempt to autocomplete - -		std::string utf8_trigger = wstring_to_utf8str(raw_text); -		std::string utf8_out_str(utf8_trigger); - -		if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) -		{ -			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); -			self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part -			S32 outlength = self->mChatBox->getLength(); // in characters - -			// Select to end of line, starting from the character -			// after the last one the user typed. -			self->mChatBox->setSelection(length, outlength); -		} -		else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) -		{ -			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); -			self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part -			self->mChatBox->setCursorToEnd(); -		} - -		//llinfos << "GESTUREDEBUG " << trigger  -		//	<< " len " << length -		//	<< " outlen " << out_str.getLength() -		//	<< llendl; -	} -} - -// static -void LLNearbyChatBar::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) -{ -	// stop typing animation -	gAgent.stopTyping(); -} - -void LLNearbyChatBar::onChatBoxFocusReceived() -{ -	mChatBox->setEnabled(!gDisconnected); -} - -EChatType LLNearbyChatBar::processChatTypeTriggers(EChatType type, std::string &str) -{ -	U32 length = str.length(); -	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); -	 -	for (S32 n = 0; n < cnt; n++) -	{ -		if (length >= sChatTypeTriggers[n].name.length()) -		{ -			std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); - -			if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) -			{ -				U32 trigger_length = sChatTypeTriggers[n].name.length(); - -				// It's to remove space after trigger name -				if (length > trigger_length && str[trigger_length] == ' ') -					trigger_length++; - -				str = str.substr(trigger_length, length); - -				if (CHAT_TYPE_NORMAL == type) -					return sChatTypeTriggers[n].type; -				else -					break; -			} -		} -	} - -	return type; -} - -void LLNearbyChatBar::sendChat( EChatType type ) -{ -	if (mChatBox) -	{ -		LLWString text = mChatBox->getConvertedText(); -		if (!text.empty()) -		{ -			// store sent line in history, duplicates will get filtered -			mChatBox->updateHistory(); -			// Check if this is destined for another channel -			S32 channel = 0; -			stripChannelNumber(text, &channel); -			 -			std::string utf8text = wstring_to_utf8str(text); -			// Try to trigger a gesture, if not chat to a script. -			std::string utf8_revised_text; -			if (0 == channel) -			{ -				// discard returned "found" boolean -				LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); -			} -			else -			{ -				utf8_revised_text = utf8text; -			} - -			utf8_revised_text = utf8str_trim(utf8_revised_text); - -			type = processChatTypeTriggers(type, utf8_revised_text); - -			if (!utf8_revised_text.empty()) -			{ -				// Chat with animation -				sendChatFromViewer(utf8_revised_text, type, TRUE); -			} -		} - -		mChatBox->setText(LLStringExplicit("")); -	} - -	gAgent.stopTyping(); - -	// If the user wants to stop chatting on hitting return, lose focus -	// and go out of chat mode. -	if (gSavedSettings.getBOOL("CloseChatOnReturn")) -	{ -		stopChat(); -	} -} - -void LLNearbyChatBar::showNearbyChatPanel(bool show) -{ -	if (!show) -	{ -		if (mNearbyChat->getVisible() && !isMinimized()) -		{ -			mExpandedHeight = getRect().getHeight(); -		} -		setResizeLimits(getMinWidth(), COLLAPSED_HEIGHT); -		mNearbyChat->setVisible(FALSE); -		reshape(getRect().getWidth(), COLLAPSED_HEIGHT); -		enableResizeCtrls(true, true, false); -		storeRectControl(); -	} -	else -	{ -		mNearbyChat->setVisible(TRUE); -		setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); -		reshape(getRect().getWidth(), mExpandedHeight); -		enableResizeCtrls(true); -		storeRectControl(); -	} - -	gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible()); -} - -void LLNearbyChatBar::onToggleNearbyChatPanel() -{ -	showNearbyChatPanel(!mNearbyChat->getVisible()); -} - -void LLNearbyChatBar::setMinimized(BOOL b) -{ -	LLNearbyChat* nearby_chat = getChild<LLNearbyChat>("nearby_chat"); -	// when unminimizing with nearby chat visible, go ahead and kill off screen chats -	if (!b && nearby_chat->getVisible()) -	{ -		nearby_chat->removeScreenChat(); -	} -		LLFloater::setMinimized(b); -} - -void LLNearbyChatBar::onChatBoxCommit() -{ -	if (mChatBox->getText().length() > 0) -	{ -		sendChat(CHAT_TYPE_NORMAL); -	} - -	gAgent.stopTyping(); -} - -void LLNearbyChatBar::displaySpeakingIndicator() -{ -	LLSpeakerMgr::speaker_list_t speaker_list; -	LLUUID id; - -	id.setNull(); -	mSpeakerMgr->update(TRUE); -	mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); - -	for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) -	{ -		LLPointer<LLSpeaker> s = *i; -		if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) -		{ -			id = s->mID; -			break; -		} -	} - -	if (!id.isNull()) -	{ -		mOutputMonitor->setVisible(TRUE); -		mOutputMonitor->setSpeakerId(id); -	} -	else -	{ -		mOutputMonitor->setVisible(FALSE); -	} -} - -void LLNearbyChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) -{ -	sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); -} - -void LLNearbyChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) -{ -	// Look for "/20 foo" channel chats. -	S32 channel = 0; -	LLWString out_text = stripChannelNumber(wtext, &channel); -	std::string utf8_out_text = wstring_to_utf8str(out_text); -	std::string utf8_text = wstring_to_utf8str(wtext); - -	utf8_text = utf8str_trim(utf8_text); -	if (!utf8_text.empty()) -	{ -		utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); -	} - -	// Don't animate for chats people can't hear (chat to scripts) -	if (animate && (channel == 0)) -	{ -		if (type == CHAT_TYPE_WHISPER) -		{ -			lldebugs << "You whisper " << utf8_text << llendl; -			gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); -		} -		else if (type == CHAT_TYPE_NORMAL) -		{ -			lldebugs << "You say " << utf8_text << llendl; -			gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); -		} -		else if (type == CHAT_TYPE_SHOUT) -		{ -			lldebugs << "You shout " << utf8_text << llendl; -			gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); -		} -		else -		{ -			llinfos << "send_chat_from_viewer() - invalid volume" << llendl; -			return; -		} -	} -	else -	{ -		if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) -		{ -			lldebugs << "Channel chat: " << utf8_text << llendl; -		} -	} - -	send_chat_from_viewer(utf8_out_text, type, channel); -} - -// static  -void LLNearbyChatBar::startChat(const char* line) -{ -	LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - -	if (!cb ) -		return; - -	cb->setVisible(TRUE); -	cb->setFocus(TRUE); -	cb->mChatBox->setFocus(TRUE); - -	if (line) -	{ -		std::string line_string(line); -		cb->mChatBox->setText(line_string); -	} - -	cb->mChatBox->setCursorToEnd(); -} - -// Exit "chat mode" and do the appropriate focus changes -// static -void LLNearbyChatBar::stopChat() -{ -	LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - -	if (!cb) -		return; - -	cb->mChatBox->setFocus(FALSE); - - 	// stop typing animation - 	gAgent.stopTyping(); -} - -// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. -// Otherwise returns input and channel 0. -LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) -{ -	if (mesg[0] == '/' -		&& mesg[1] == '/') -	{ -		// This is a "repeat channel send" -		*channel = sLastSpecialChatChannel; -		return mesg.substr(2, mesg.length() - 2); -	} -	else if (mesg[0] == '/' -			 && mesg[1] -			 && LLStringOps::isDigit(mesg[1])) -	{ -		// This a special "/20" speak on a channel -		S32 pos = 0; - -		// Copy the channel number into a string -		LLWString channel_string; -		llwchar c; -		do -		{ -			c = mesg[pos+1]; -			channel_string.push_back(c); -			pos++; -		} -		while(c && pos < 64 && LLStringOps::isDigit(c)); -		 -		// Move the pointer forward to the first non-whitespace char -		// Check isspace before looping, so we can handle "/33foo" -		// as well as "/33 foo" -		while(c && iswspace(c)) -		{ -			c = mesg[pos+1]; -			pos++; -		} -		 -		sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); -		*channel = sLastSpecialChatChannel; -		return mesg.substr(pos, mesg.length() - pos); -	} -	else -	{ -		// This is normal chat. -		*channel = 0; -		return mesg; -	} -} - -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) -{ -	LLMessageSystem* msg = gMessageSystem; -	msg->newMessageFast(_PREHASH_ChatFromViewer); -	msg->nextBlockFast(_PREHASH_AgentData); -	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -	msg->nextBlockFast(_PREHASH_ChatData); -	msg->addStringFast(_PREHASH_Message, utf8_out_text); -	msg->addU8Fast(_PREHASH_Type, type); -	msg->addS32("Channel", channel); - -	gAgent.sendReliableMessage(); - -	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); -} - -class LLChatCommandHandler : public LLCommandHandler -{ -public: -	// not allowed from outside the app -	LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } - -    // Your code here -	bool handle(const LLSD& tokens, const LLSD& query_map, -				LLMediaCtrl* web) -	{ -		bool retval = false; -		// Need at least 2 tokens to have a valid message. -		if (tokens.size() < 2) -		{ -			retval = false; -		} -		else -		{ -		S32 channel = tokens[0].asInteger(); -			// VWR-19499 Restrict function to chat channels greater than 0. -			if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) -			{ -				retval = true; -		// Send unescaped message, see EXT-6353. -		std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); -		send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); -			} -			else -			{ -				retval = false; -				// Tell us this is an unsupported SLurl. -			} -		} -		return retval; -	} -}; - -// Creating the object registers with the dispatcher. -LLChatCommandHandler gChatHandler; - - diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h deleted file mode 100644 index 662496d338..0000000000 --- a/indra/newview/llnearbychatbar.h +++ /dev/null @@ -1,104 +0,0 @@ -/**  - * @file llnearbychatbar.h - * @brief LLNearbyChatBar class definition - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLNEARBYCHATBAR_H -#define LL_LLNEARBYCHATBAR_H - -#include "llfloater.h" -#include "llcombobox.h" -#include "llgesturemgr.h" -#include "llchat.h" -#include "llvoiceclient.h" -#include "lloutputmonitorctrl.h" -#include "llspeakers.h" - -class LLNearbyChatBarListener; - -class LLNearbyChatBar :	public LLFloater -{ -	LOG_CLASS(LLNearbyChatBar); - -public: -	// constructor for inline chat-bars (e.g. hosted in chat history window) -	LLNearbyChatBar(const LLSD& key); -	~LLNearbyChatBar() {} - -	virtual BOOL postBuild(); -	/*virtual*/ void onOpen(const LLSD& key); - -	static LLNearbyChatBar* getInstance(); - -	LLLineEditor* getChatBox() { return mChatBox; } - -	virtual void draw(); - -	std::string getCurrentChat(); -	virtual BOOL handleKeyHere( KEY key, MASK mask ); - -	static void startChat(const char* line); -	static void stopChat(); - -	static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); -	static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); - -	void showHistory(); -	void showTranslationCheckbox(BOOL show); -	/*virtual*/void setMinimized(BOOL b); - -protected: -	static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); -	static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); -	static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); -	void onChatBoxFocusReceived(); - -	void sendChat( EChatType type ); -	void onChatBoxCommit(); -	void onChatFontChange(LLFontGL* fontp); - -	/* virtual */ bool applyRectControl(); - -	void showNearbyChatPanel(bool show); -	void onToggleNearbyChatPanel(); - -	static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); -	EChatType processChatTypeTriggers(EChatType type, std::string &str); - -	void displaySpeakingIndicator(); - -	// Which non-zero channel did we last chat on? -	static S32 sLastSpecialChatChannel; - -	LLLineEditor*			mChatBox; -	LLView*					mNearbyChat; -	LLOutputMonitorCtrl*	mOutputMonitor; -	LLLocalSpeakerMgr*		mSpeakerMgr; - -	S32 mExpandedHeight; - -	boost::shared_ptr<LLNearbyChatBarListener> mListener; -}; - -#endif diff --git a/indra/newview/llnearbychatbarlistener.cpp b/indra/newview/llnearbychatbarlistener.cpp index a63e1fb76e..61815d1864 100644 --- a/indra/newview/llnearbychatbarlistener.cpp +++ b/indra/newview/llnearbychatbarlistener.cpp @@ -29,14 +29,14 @@  #include "llviewerprecompiledheaders.h"  #include "llnearbychatbarlistener.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llagent.h"  #include "llchat.h" -LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChatBar & chatbar) +LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChat & chatbar)    : LLEventAPI("LLChatBar",                 "LLChatBar listener to (e.g.) sendChat, etc."),  	mChatbar(chatbar) diff --git a/indra/newview/llnearbychatbarlistener.h b/indra/newview/llnearbychatbarlistener.h index 9af9bc1f7b..0537275424 100644 --- a/indra/newview/llnearbychatbarlistener.h +++ b/indra/newview/llnearbychatbarlistener.h @@ -33,17 +33,17 @@  #include "lleventapi.h"  class LLSD; -class LLNearbyChatBar; +class LLNearbyChat;  class LLNearbyChatBarListener : public LLEventAPI  {  public: -	LLNearbyChatBarListener(LLNearbyChatBar & chatbar); +	LLNearbyChatBarListener(LLNearbyChat & chatbar);  private:      void sendChat(LLSD const & chat_data) const; -	LLNearbyChatBar & mChatbar; +	LLNearbyChat & mChatbar;  };  #endif // LL_LLNEARBYCHATBARLISTENER_H diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 600fd395fb..c97e3585e1 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -1,6 +1,6 @@  /**    * @file LLNearbyChatHandler.cpp - * @brief Nearby chat notification managment + * @brief Nearby chat chat managment   *   * $LicenseInfo:firstyear=2009&license=viewerlgpl$   * Second Life Viewer Source Code @@ -40,22 +40,24 @@  #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance  #include "llviewerwindow.h"//for screen channel position -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llrootview.h"  #include "lllayoutstack.h"  //add LLNearbyChatHandler to LLNotificationsUI namespace  using namespace LLNotificationsUI; -//----------------------------------------------------------------------------------------------- -//LLNearbyChatScreenChannel -//-----------------------------------------------------------------------------------------------	 -LLToastPanelBase* createToastPanel() +static LLNearbyChatToastPanel* createToastPanel()  {  	LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance();  	return item;  } + +//----------------------------------------------------------------------------------------------- +//LLNearbyChatScreenChannel +//-----------------------------------------------------------------------------------------------	 +  class LLNearbyChatScreenChannel: public LLScreenChannelBase  {  	LOG_CLASS(LLNearbyChatScreenChannel); @@ -81,10 +83,10 @@ public:  		}  	} -	void addNotification	(LLSD& notification); +	void addChat	(LLSD& chat);  	void arrangeToasts		(); -	typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t; +	typedef boost::function<LLNearbyChatToastPanel* (void )> create_toast_panel_callback_t;  	void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;}  	void onToastDestroyed	(LLToast* toast, bool app_quitting); @@ -152,6 +154,8 @@ protected:  	bool	mChannelRect;  }; + +  //-----------------------------------------------------------------------------------------------  // LLNearbyChatToast  //----------------------------------------------------------------------------------------------- @@ -255,7 +259,7 @@ void LLNearbyChatScreenChannel::updateToastFadingTime()  bool	LLNearbyChatScreenChannel::createPoolToast()  { -	LLToastPanelBase* panel= m_create_toast_panel_callback_t(); +	LLNearbyChatToastPanel* panel= m_create_toast_panel_callback_t();  	if(!panel)  		return false; @@ -277,7 +281,7 @@ bool	LLNearbyChatScreenChannel::createPoolToast()  	return true;  } -void LLNearbyChatScreenChannel::addNotification(LLSD& notification) +void LLNearbyChatScreenChannel::addChat(LLSD& chat)  {  	//look in pool. if there is any message  	if(mStopProcessing) @@ -289,8 +293,8 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  	if(m_active_toasts.size())  	{ -		LLUUID fromID = notification["from_id"].asUUID();		// agent id or object id -		std::string from = notification["from"].asString(); +		LLUUID fromID = chat["from_id"].asUUID();		// agent id or object id +		std::string from = chat["from"].asString();  		LLToast* toast = m_active_toasts[0].get();  		if (toast)  		{ @@ -298,7 +302,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  			if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText())  			{ -				panel->addMessage(notification); +				panel->addMessage(chat);  				toast->reshapeToPanel();  				toast->startTimer(); @@ -316,11 +320,11 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  		LL_DEBUGS("NearbyChat") << "Empty pool" << llendl;  		if(!createPoolToast())//created toast will go to pool. so next call will find it  			return; -		addNotification(notification); +		addChat(chat);  		return;  	} -	int chat_type = notification["chat_type"].asInteger(); +	int chat_type = chat["chat_type"].asInteger();  	if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG))  	{ @@ -339,10 +343,10 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  	m_toast_pool.pop_back(); -	LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel()); +	LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());  	if(!panel)  		return; -	panel->init(notification); +	panel->init(chat);  	toast->reshapeToPanel();  	toast->startTimer(); @@ -445,10 +449,8 @@ void LLNearbyChatScreenChannel::arrangeToasts()  //-----------------------------------------------------------------------------------------------  boost::scoped_ptr<LLEventPump> LLNearbyChatHandler::sChatWatcher(new LLEventStream("LLChat")); -LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id) +LLNearbyChatHandler::LLNearbyChatHandler()  { -	mType = type; -  	// Getting a Channel for our notifications  	LLNearbyChatScreenChannel::Params p;  	p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); @@ -485,28 +487,26 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	if(chat_msg.mText.empty())  		return;//don't process empty messages -	LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - -	LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); +	LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();  	// Build notification data  -	LLSD notification; -	notification["message"] = chat_msg.mText; -	notification["from"] = chat_msg.mFromName; -	notification["from_id"] = chat_msg.mFromID; -	notification["time"] = chat_msg.mTime; -	notification["source"] = (S32)chat_msg.mSourceType; -	notification["chat_type"] = (S32)chat_msg.mChatType; -	notification["chat_style"] = (S32)chat_msg.mChatStyle; +	LLSD chat; +	chat["message"] = chat_msg.mText; +	chat["from"] = chat_msg.mFromName; +	chat["from_id"] = chat_msg.mFromID; +	chat["time"] = chat_msg.mTime; +	chat["source"] = (S32)chat_msg.mSourceType; +	chat["chat_type"] = (S32)chat_msg.mChatType; +	chat["chat_style"] = (S32)chat_msg.mChatStyle;  	// Pass sender info so that it can be rendered properly (STORM-1021). -	notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); +	chat["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);  	if (chat_msg.mChatType == CHAT_TYPE_DIRECT &&  		chat_msg.mText.length() > 0 &&  		chat_msg.mText[0] == '@')  	{  		// Send event on to LLEventStream and exit -		sChatWatcher->post(notification); +		sChatWatcher->post(chat);  		return;  	} @@ -553,11 +553,9 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	}  	// Send event on to LLEventStream -	sChatWatcher->post(notification); +	sChatWatcher->post(chat); - -	if( !chat_bar->isMinimized() -		&& nearby_chat->isInVisibleChain()  +	if( nearby_chat->isInVisibleChain()  		|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT  			&& gSavedSettings.getBOOL("UseChatBubbles") )  		|| mChannel.isDead() @@ -604,23 +602,19 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  		// Add a nearby chat toast.  		LLUUID id;  		id.generate(); -		notification["id"] = id; +		chat["id"] = id;  		std::string r_color_name = "White";  		F32 r_color_alpha = 1.0f;   		LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); -		notification["text_color"] = r_color_name; -		notification["color_alpha"] = r_color_alpha; -		notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ; -		notification["message"] = toast_msg; -		channel->addNotification(notification);	 +		chat["text_color"] = r_color_name; +		chat["color_alpha"] = r_color_alpha; +		chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; +		chat["message"] = toast_msg; +		channel->addChat(chat);	  	}  } -void LLNearbyChatHandler::onDeleteToast(LLToast* toast) -{ -} -  //-----------------------------------------------------------------------------------------------  // LLNearbyChatToast diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h index b0e4f62d51..a5034ac1cb 100644 --- a/indra/newview/llnearbychathandler.h +++ b/indra/newview/llnearbychathandler.h @@ -37,14 +37,13 @@ namespace LLNotificationsUI{  class LLNearbyChatHandler : public LLChatHandler  {  public: -	LLNearbyChatHandler(e_notification_type type,const LLSD& id); +	LLNearbyChatHandler();  	virtual ~LLNearbyChatHandler();  	virtual void processChat(const LLChat& chat_msg, const LLSD &args);  protected: -	virtual void onDeleteToast(LLToast* toast);  	virtual void initChannel();  	static boost::scoped_ptr<LLEventPump> sChatWatcher; diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 89fe7bb3c2..2bc9cdd3c1 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -40,10 +40,10 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsModal(false) +LLAlertHandler::LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal)  +:	LLSysHandler(name, notification_type), +	mIsModal(is_modal)  { -	mType = type; -  	LLScreenChannelBase::Params p;  	p.id = LLUUID(gSavedSettings.getString("AlertChannelUUID"));  	p.display_toasts_always = true; @@ -68,79 +68,58 @@ void LLAlertHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLAlertHandler::processNotification(const LLSD& notify) +bool LLAlertHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") +	if (notification->canLogToIM() && notification->hasFormElements())  	{ -		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(); -		p.notification = notification; -		p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); -		p.enable_hide_btn = false; -		p.can_fade = false; -		p.is_modal = mIsModal; -		p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); - -		// Show alert in middle of progress view (during teleport) (EXT-1093) -		LLProgressView* progress = gViewerWindow->getProgressView(); -		LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); -		mChannel.get()->updatePositionAndSize(rc); - -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); -	} -	else if (notify["sigtype"].asString() == "change") -	{ -		LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); -	} -	else -	{ -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->killToastByNotificationID(notification->getID()); +		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(); +	p.notification = notification; +	p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); +	p.enable_hide_btn = false; +	p.can_fade = false; +	p.is_modal = mIsModal; +	p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); + +	// Show alert in middle of progress view (during teleport) (EXT-1093) +	LLProgressView* progress = gViewerWindow->getProgressView(); +	LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); +	mChannel.get()->updatePositionAndSize(rc); + +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); +	  	return false;  } -//-------------------------------------------------------------------------- - -void LLAlertHandler::onDeleteToast(LLToast* toast) +void LLAlertHandler::onChange( LLNotificationPtr notification )  { +	LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog);  } - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index ad51389241..18cd94e685 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -37,15 +37,13 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id) +LLGroupHandler::LLGroupHandler() +:	LLSysHandler("Group Notifications", "groupnotify")  { -	mType = type; -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{ -		channel->setOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -64,72 +62,37 @@ void LLGroupHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLGroupHandler::processNotification(const LLSD& notify) +bool LLGroupHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{ -		LLHandlerUtil::logGroupNoticeToIMGroup(notification); +	LLHandlerUtil::logGroupNoticeToIMGroup(notification); -		LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.notification = notification; -		p.panel = notify_box; -		p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); +	LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.notification = notification; +	p.panel = notify_box; +	p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); -		// send a signal to the counter manager -		mNewNotificationSignal(); +	LLGroupActions::refresh_notices(); -		LLGroupActions::refresh_notices(); -	} -	else if (notify["sigtype"].asString() == "delete") -	{ -		mChannel.get()->killToastByNotificationID(notification->getID()); -	}  	return false;  } -//-------------------------------------------------------------------------- -void LLGroupHandler::onDeleteToast(LLToast* toast) -{ -	// send a signal to the counter manager -	mDelNotificationSignal(); - -	// send a signal to a listener to let him perform some action -	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list -	mNotificationIDSignal(toast->getNotificationID()); -} - -//-------------------------------------------------------------------------- -void LLGroupHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); - -	if (notification && LLNotificationManager::getInstance()->getHandlerForNotification(notification->getType()) == this) -	{ -		LLNotifications::instance().cancel(notification); -	} -}  //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 3569ad6447..0899625242 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -30,7 +30,7 @@  #include "llwindow.h" -//#include "llnotificationsutil.h" +#include "llnotifications.h"  #include "llchannelmanager.h"  #include "llchat.h"  #include "llinstantmessage.h" @@ -40,20 +40,6 @@ class LLIMFloater;  namespace LLNotificationsUI  { -// ENotificationType enumerates all possible types of notifications that could be met -//  -typedef enum e_notification_type -{ -	NT_NOTIFY,  -	NT_NOTIFYTIP, -	NT_GROUPNOTIFY, -	NT_IMCHAT,  -	NT_GROUPCHAT,  -	NT_NEARBYCHAT,  -	NT_ALERT, -	NT_ALERTMODAL, -	NT_OFFER -} ENotificationType;  /**   * Handler of notification events. @@ -81,21 +67,8 @@ class LLEventHandler  public:  	virtual ~LLEventHandler() {}; -	// callbacks for counters -	typedef boost::function<void (void)> notification_callback_t; -	typedef boost::signals2::signal<void (void)> notification_signal_t; -	notification_signal_t mNewNotificationSignal; -	notification_signal_t mDelNotificationSignal; -	boost::signals2::connection setNewNotificationCallback(notification_callback_t cb) { return mNewNotificationSignal.connect(cb); } -	boost::signals2::connection setDelNotification(notification_callback_t cb) { return mDelNotificationSignal.connect(cb); } -	// callback for notification/toast -	typedef boost::function<void (const LLUUID id)> notification_id_callback_t; -	typedef boost::signals2::signal<void (const LLUUID id)> notification_id_signal_t; -	notification_id_signal_t mNotificationIDSignal; -	boost::signals2::connection setNotificationIDCallback(notification_id_callback_t cb) { return mNotificationIDSignal.connect(cb); } -  protected: -	virtual void onDeleteToast(LLToast* toast)=0; +	virtual void onDeleteToast(LLToast* toast) {}  	// arrange handler's channel on a screen  	// is necessary to unbind a moment of creation of a channel and a moment of positioning of it @@ -104,8 +77,6 @@ protected:  	virtual void initChannel()=0;  	LLHandle<LLScreenChannelBase>	mChannel; -	e_notification_type				mType; -  };  // LLSysHandler and LLChatHandler are more specific base classes @@ -115,20 +86,18 @@ protected:  /**   * Handler for system notifications.   */ -class LLSysHandler : public LLEventHandler +class LLSysHandler : public LLEventHandler, public LLNotificationChannel  {  public: -	LLSysHandler(); +	LLSysHandler(const std::string& name, const std::string& notification_type);  	virtual ~LLSysHandler() {}; -	virtual bool processNotification(const LLSD& notify)=0; - -protected : -	static void init(); -	void removeExclusiveNotifications(const LLNotificationPtr& notif); +	// base interface functions +	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} -	typedef std::list< std::set<std::string> > exclusive_notif_sets; -	static exclusive_notif_sets sExclusiveNotificationGroups; +	virtual bool processNotification(const LLNotificationPtr& notify)=0;  };  /** @@ -149,15 +118,12 @@ public:  class LLIMHandler : public LLSysHandler  {  public: -	LLIMHandler(e_notification_type type, const LLSD& id); +	LLIMHandler();  	virtual ~LLIMHandler(); -	// base interface functions -	virtual bool processNotification(const LLSD& notify); -  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void initChannel(); +	bool processNotification(const LLNotificationPtr& p); +	/*virtual*/ void initChannel();  };  /** @@ -167,16 +133,15 @@ protected:  class LLTipHandler : public LLSysHandler  {  public: -	LLTipHandler(e_notification_type type, const LLSD& id); +	LLTipHandler();  	virtual ~LLTipHandler();  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void onRejectToast(const LLUUID& id); -	virtual void initChannel(); +	/*virtual*/ void initChannel();  };  /** @@ -186,18 +151,16 @@ protected:  class LLScriptHandler : public LLSysHandler  {  public: -	LLScriptHandler(e_notification_type type, const LLSD& id); +	LLScriptHandler();  	virtual ~LLScriptHandler(); +	/*virtual*/ void onDelete(LLNotificationPtr p);  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id); +	/*virtual*/ void onDeleteToast(LLToast* toast); +	/*virtual*/ void initChannel();  }; @@ -207,18 +170,15 @@ protected:  class LLGroupHandler : public LLSysHandler  {  public: -	LLGroupHandler(e_notification_type type, const LLSD& id); +	LLGroupHandler();  	virtual ~LLGroupHandler();  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast);  	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id);  };  /** @@ -227,16 +187,14 @@ protected:  class LLAlertHandler : public LLSysHandler  {  public: -	LLAlertHandler(e_notification_type type, const LLSD& id); +	LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal);  	virtual ~LLAlertHandler(); -	void setAlertMode(bool is_modal) { mIsModal = is_modal; } - -	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p); +	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast);  	virtual void initChannel();  	bool	mIsModal; @@ -249,102 +207,71 @@ protected:  class LLOfferHandler : public LLSysHandler  {  public: -	LLOfferHandler(e_notification_type type, const LLSD& id); +	LLOfferHandler();  	virtual ~LLOfferHandler();  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p); +	/*virtual*/ void onDelete(LLNotificationPtr notification); +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id); +	/*virtual*/ void initChannel();  };  /**   * Handler for UI hints.   */ -class LLHintHandler : public LLSingleton<LLHintHandler> +class LLHintHandler : public LLNotificationChannel  {  public: -	LLHintHandler(); -	virtual ~LLHintHandler(); +	LLHintHandler() : LLNotificationChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")) +	{} +	virtual ~LLHintHandler() {} -	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onAdd(LLNotificationPtr p); +	/*virtual*/ void onLoad(LLNotificationPtr p); +	/*virtual*/ void onDelete(LLNotificationPtr p);  };  /**   * Handler for browser notifications   */ -class LLBrowserNotification : public LLSingleton<LLBrowserNotification> +class LLBrowserNotification : public LLNotificationChannel  {  public: -	virtual bool processNotification(const LLSD& notify); +	LLBrowserNotification() +	: LLNotificationChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")) +	{} +	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	bool processNotification(const LLNotificationPtr& p);  };  /**   * Handler for outbox notifications   */ -class LLOutboxNotification : public LLSingleton<LLOutboxNotification> +class LLOutboxNotification : public LLNotificationChannel  {  public: -	virtual bool processNotification(const LLSD& notify); +	LLOutboxNotification() +	:	LLNotificationChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")) +	{} +	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onChange(LLNotificationPtr p) { } +	/*virtual*/ void onDelete(LLNotificationPtr p); +	bool processNotification(const LLNotificationPtr& p);  };  class LLHandlerUtil  {  public:  	/** -	 * Checks sufficient conditions to log notification message to IM session. -	 */ -	static bool canLogToIM(const LLNotificationPtr& notification); - -	/** -	 * Checks sufficient conditions to log notification message to nearby chat session. -	 */ -	static bool canLogToNearbyChat(const LLNotificationPtr& notification); - -	/** -	 * Checks sufficient conditions to spawn IM session. -	 */ -	static bool canSpawnIMSession(const LLNotificationPtr& notification); - -	/** -	 * Checks sufficient conditions to add notification toast panel IM floater. -	 */ -	static bool canAddNotifPanelToIM(const LLNotificationPtr& notification); - -	/** -	 * Checks whether notification can be used multiple times or not. -	 */ -	static bool isNotificationReusable(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); - -	/** -	 * Checks if passed notification can create toast. -	 */ -	static bool canSpawnToast(const LLNotificationPtr& notification); - -	/**  	 * Determines whether IM floater is opened.  	 */  	static bool isIMFloaterOpened(const LLNotificationPtr& notification);  	/** -	* Determines whether IM floater is focused. -	*/ -	static bool isIMFloaterFocused(const LLNotificationPtr& notification); - -	/**  	 * Writes notification message to IM session.  	 */  	static void logToIM(const EInstantMessage& session_type, @@ -355,12 +282,7 @@ public:  	/**  	 * Writes notification message to IM  p2p session.  	 */ -	static void logToIMP2P(const LLNotificationPtr& notification); - -	/** -	 * Writes notification message to IM  p2p session. -	 */ -	static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only); +	static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only = false);  	/**  	 * Writes group notice notification message to IM  group session. @@ -406,13 +328,6 @@ public:  	 */  	static void decIMMesageCounter(const LLNotificationPtr& notification); -private: - -	/** -	 * Find IM floater based on "from_id" -	 */ -	static LLIMFloater* findIMFloater(const LLNotificationPtr& notification); -  };  } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 16c51138a9..cba22b233b 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -41,212 +41,19 @@  using namespace LLNotificationsUI; -// static -std::list< std::set<std::string> > LLSysHandler::sExclusiveNotificationGroups; - -// static -void LLSysHandler::init() -{ -	std::set<std::string> online_offline_group; -	online_offline_group.insert("FriendOnline"); -	online_offline_group.insert("FriendOffline"); - -	sExclusiveNotificationGroups.push_back(online_offline_group); -} - -LLSysHandler::LLSysHandler() -{ -	if(sExclusiveNotificationGroups.empty()) -	{ -		init(); -	} -} - -void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) -{ -	LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel.get()); -	if (channel == NULL) -	{ -		return; -	} - -	class ExclusiveMatcher: public LLScreenChannel::Matcher -	{ -	public: -		ExclusiveMatcher(const std::set<std::string>& excl_group, -				const std::string& from_name) : -			mExclGroup(excl_group), mFromName(from_name) -		{ -		} -		bool matches(const LLNotificationPtr notification) const -		{ -			for (std::set<std::string>::const_iterator it = mExclGroup.begin(); it -					!= mExclGroup.end(); it++) -			{ -				std::string from_name = LLHandlerUtil::getSubstitutionName(notification); -				if (notification->getName() == *it && from_name == mFromName) -				{ -					return true; -				} -			} -			return false; -		} -	private: -		const std::set<std::string>& mExclGroup; -		const std::string& mFromName; -	}; - - -	for (exclusive_notif_sets::iterator it = sExclusiveNotificationGroups.begin(); it -			!= sExclusiveNotificationGroups.end(); it++) -	{ -		std::set<std::string> group = *it; -		std::set<std::string>::iterator g_it = group.find(notif->getName()); -		if (g_it != group.end()) -		{ -			channel->killMatchedToasts(ExclusiveMatcher(group, -					LLHandlerUtil::getSubstitutionName(notif))); -		} -	} -} - -const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), -		REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), -		OBJECT_GIVE_ITEM("ObjectGiveItem"), -		OBJECT_GIVE_ITEM_UNKNOWN_USER("ObjectGiveItemUnknownUser"), -						PAYMENT_RECEIVED("PaymentReceived"), -						PAYMENT_SENT("PaymentSent"), -						ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), -						USER_GIVE_ITEM("UserGiveItem"), -						INVENTORY_ACCEPTED("InventoryAccepted"), -						INVENTORY_DECLINED("InventoryDeclined"), -						OFFER_FRIENDSHIP("OfferFriendship"), -						FRIENDSHIP_ACCEPTED("FriendshipAccepted"), -						FRIENDSHIP_OFFERED("FriendshipOffered"), -						FRIENDSHIP_ACCEPTED_BYME("FriendshipAcceptedByMe"), -						FRIENDSHIP_DECLINED_BYME("FriendshipDeclinedByMe"), -						FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), -						SERVER_OBJECT_MESSAGE("ServerObjectMessage"), -						TELEPORT_OFFERED("TeleportOffered"), -						TELEPORT_OFFERED_MATURITY_EXCEEDED("TeleportOffered_MaturityExceeded"), -						TELEPORT_OFFERED_MATURITY_BLOCKED("TeleportOffered_MaturityBlocked"), -						TELEPORT_OFFER_SENT("TeleportOfferSent"), -						IM_SYSTEM_MESSAGE_TIP("IMSystemMessageTip"); - +LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type) +:	LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type)) +{}  // static -bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) -{ -	return GRANTED_MODIFY_RIGHTS == notification->getName() -			|| REVOKED_MODIFY_RIGHTS == notification->getName() -			|| PAYMENT_RECEIVED == notification->getName() -			|| PAYMENT_SENT == notification->getName() -			|| OFFER_FRIENDSHIP == notification->getName() -			|| FRIENDSHIP_OFFERED == notification->getName() -			|| FRIENDSHIP_ACCEPTED == notification->getName() -			|| FRIENDSHIP_ACCEPTED_BYME == notification->getName() -			|| FRIENDSHIP_DECLINED_BYME == notification->getName() -			|| SERVER_OBJECT_MESSAGE == notification->getName() -			|| INVENTORY_ACCEPTED == notification->getName() -			|| INVENTORY_DECLINED == notification->getName() -			|| USER_GIVE_ITEM == notification->getName() -			|| TELEPORT_OFFERED == notification->getName() -			|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -			|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName() -			|| TELEPORT_OFFER_SENT == notification->getName() -			|| IM_SYSTEM_MESSAGE_TIP == notification->getName(); -} - -// static -bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) -{ -	return notification->getType() == "notifytip" -			&&  FRIEND_ONLINE != notification->getName() -			&& FRIEND_OFFLINE != notification->getName() -			&& INVENTORY_ACCEPTED != notification->getName() -			&& INVENTORY_DECLINED != notification->getName() -			&& IM_SYSTEM_MESSAGE_TIP != notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) -{ -	return OFFER_FRIENDSHIP == notification->getName() -			|| USER_GIVE_ITEM == notification->getName() -			|| TELEPORT_OFFERED == notification->getName() -			|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -			|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); -} - -// static -bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification) -{ -	return OFFER_FRIENDSHIP == notification->getName() -					|| USER_GIVE_ITEM == notification->getName() -					|| TELEPORT_OFFERED == notification->getName() -					|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -					|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); -} - -// static -bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification) -{ -	return OFFER_FRIENDSHIP == notification->getName() -		|| USER_GIVE_ITEM == notification->getName() -		|| TELEPORT_OFFERED == notification->getName() -		|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -		|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification) -{ -	return canLogToIM(notification) && canSpawnIMSession(notification); -} - -// static -bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) +bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification)  { -	if(INVENTORY_DECLINED == notification->getName()  -		|| INVENTORY_ACCEPTED == notification->getName()) -	{ -		// return false for inventory accepted/declined notifications if respective IM window is open (EXT-5909) -		return ! isIMFloaterOpened(notification); -	} - -	if(FRIENDSHIP_ACCEPTED == notification->getName()) -	{ -		// don't show FRIENDSHIP_ACCEPTED if IM window is opened and focused - EXT-6441 -		return ! isIMFloaterFocused(notification); -	} - -	if(OFFER_FRIENDSHIP == notification->getName() -		|| USER_GIVE_ITEM == notification->getName() -		|| TELEPORT_OFFERED == notification->getName() -		|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -		|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName()) -	{ -		// When ANY offer arrives, show toast, unless IM window is already open - EXT-5904 -		return ! isIMFloaterOpened(notification); -	} - -	return true; -} +	bool res = false; -// static -LLIMFloater* LLHandlerUtil::findIMFloater(const LLNotificationPtr& notification) -{  	LLUUID from_id = notification->getPayload()["from_id"];  	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); -	return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -} - -// static -bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) -{ -	bool res = false; +	LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -	LLIMFloater* im_floater = findIMFloater(notification);  	if (im_floater != NULL)  	{  		res = im_floater->getVisible() == TRUE; @@ -255,19 +62,6 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification)  	return res;  } -bool LLHandlerUtil::isIMFloaterFocused(const LLNotificationPtr& notification) -{ -	bool res = false; - -	LLIMFloater* im_floater = findIMFloater(notification); -	if (im_floater != NULL) -	{ -		res = im_floater->hasFocus() == TRUE; -	} - -	return res; -} -  // static  void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  		const std::string& session_name, const std::string& from_name, @@ -329,12 +123,6 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  	}  } -// static -void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification) -{ -	logToIMP2P(notification, false); -} -  void log_name_callback(const std::string& full_name, const std::string& from_name,   					   const std::string& message, const LLUUID& from_id) @@ -346,9 +134,6 @@ void log_name_callback(const std::string& full_name, const std::string& from_nam  // static  void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only)  { -	// don't create IM p2p session with objects, it's necessary condition to log -	if (notification->getName() != OBJECT_GIVE_ITEM) -	{  		LLUUID from_id = notification->getPayload()["from_id"];  		if (from_id.isNull()) @@ -366,7 +151,6 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_fi  			gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id));  		}  	} -}  // static  void LLHandlerUtil::logGroupNoticeToIMGroup( @@ -501,14 +285,10 @@ void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification)  	LLUUID from_id = notification->getPayload()["from_id"];  	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); -	LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession( -			session_id); +	LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession(session_id); -	if (session == NULL) +	if (session)  	{ -		return; -	} -  	LLSD arg;  	arg["session_id"] = session_id;  	session->mNumUnread--; @@ -517,3 +297,5 @@ void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification)  	arg["participant_unread"] = session->mParticipantUnreadMessageCount;  	LLIMModel::getInstance()->mNewMsgSignal(arg);  } +} + diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index f7163cb04f..271f418507 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -33,26 +33,6 @@  using namespace LLNotificationsUI; -LLHintHandler::LLHintHandler() -{ -} - -LLHintHandler::~LLHintHandler() -{ -} - -bool LLHintHandler::processNotification(const LLSD& notify) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	std::string sigtype = notify["sigtype"].asString(); -	if (sigtype == "add" || sigtype == "load") -	{ -		LLHints::show(notification); -	} -	else if (sigtype == "delete") -	{ -		LLHints::hide(notification); -	} -	return false; -} +void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onLoad(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); } diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index f792f53ac5..2862ad6962 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -42,107 +42,35 @@ using namespace LLNotificationsUI;  //--------------------------------------------------------------------------  LLNotificationManager::LLNotificationManager()  { -	mNotifyHandlers.clear();  	init();  }  //--------------------------------------------------------------------------  LLNotificationManager::~LLNotificationManager()  { -	BOOST_FOREACH(listener_pair_t& pair, mChannelListeners) -	{ -		pair.second.disconnect(); -	}  }  //--------------------------------------------------------------------------  void LLNotificationManager::init()  { -	LLNotificationChannel::buildChannel("Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notify")); -	LLNotificationChannel::buildChannel("NotificationTips", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytip")); -	LLNotificationChannel::buildChannel("Group Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "groupnotify")); -	LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); -	LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); -	LLNotificationChannel::buildChannel("IM Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytoast")); -	LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer")); -	LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")); -	LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")); -	LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")); +	mChannels.push_back(new LLScriptHandler()); +	mChannels.push_back(new LLTipHandler()); +	mChannels.push_back(new LLGroupHandler()); +	mChannels.push_back(new LLAlertHandler("Alerts", "alert", false)); +	mChannels.push_back(new LLAlertHandler("AlertModal", "alertmodal", true)); +	mChannels.push_back(new LLOfferHandler()); +	mChannels.push_back(new LLHintHandler()); +	mChannels.push_back(new LLBrowserNotification()); +	mChannels.push_back(new LLOutboxNotification()); +	mChannels.push_back(new LLIMHandler()); -	mChannelListeners["Notifications"] = LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["NotificationTips"] = LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Group Notifications"] = LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Alerts"] = LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["AlertModal"] = LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["IM Notifications"] = LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Offer"] = LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Hints"] = LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); -	mChannelListeners["Browser"] = LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); -	mChannelListeners["Outbox"] = LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); - -	mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD())); -	mNotifyHandlers["notifytip"] =  boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); -	mNotifyHandlers["groupnotify"] = boost::shared_ptr<LLEventHandler>(new LLGroupHandler(NT_GROUPNOTIFY, LLSD())); -	mNotifyHandlers["alert"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD())); -	mNotifyHandlers["alertmodal"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD())); -	static_cast<LLAlertHandler*>(mNotifyHandlers["alertmodal"].get())->setAlertMode(true); -	mNotifyHandlers["notifytoast"] = boost::shared_ptr<LLEventHandler>(new LLIMHandler(NT_IMCHAT, LLSD())); -	 -	mNotifyHandlers["nearbychat"] = boost::shared_ptr<LLEventHandler>(new LLNearbyChatHandler(NT_NEARBYCHAT, LLSD())); -	mNotifyHandlers["offer"] = boost::shared_ptr<LLEventHandler>(new LLOfferHandler(NT_OFFER, LLSD())); -} - -//-------------------------------------------------------------------------- -bool LLNotificationManager::onNotification(const LLSD& notify) -{ -	LLSysHandler* handle = NULL; - -	if (LLNotifications::destroyed()) -		return false; - -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); -	 -	if (!notification)  -		return false; - -	std::string notification_type = notification->getType(); -	handle = static_cast<LLSysHandler*>(mNotifyHandlers[notification_type].get()); - -	if(!handle) -		return false; -	 -	return handle->processNotification(notify); +	mChatHandler = boost::shared_ptr<LLNearbyChatHandler>(new LLNearbyChatHandler());  }  //--------------------------------------------------------------------------  void LLNotificationManager::onChat(const LLChat& msg, const LLSD &args)  { -	// check ENotificationType argument -	switch(args["type"].asInteger()) -	{ -	case NT_NEARBYCHAT: -		{ -			LLNearbyChatHandler* handle = dynamic_cast<LLNearbyChatHandler*>(mNotifyHandlers["nearbychat"].get()); - -			if(handle) -				handle->processChat(msg, args); -		} -		break; -	default: 	//no need to handle all enum types -		break; -	} -} - -//-------------------------------------------------------------------------- -LLEventHandler* LLNotificationManager::getHandlerForNotification(std::string notification_type)  -{  -	std::map<std::string, boost::shared_ptr<LLEventHandler> >::iterator it = mNotifyHandlers.find(notification_type); - -	if(it != mNotifyHandlers.end()) -		return (*it).second.get(); - -	return NULL; +	if(mChatHandler) +		mChatHandler->processChat(msg, args);  } -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 27b6ba1c71..c8afdf9e46 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -28,8 +28,6 @@  #ifndef LL_LLNOTIFICATIONMANAGER_H  #define LL_LLNOTIFICATIONMANAGER_H -#include "llevents.h" -  #include "lluictrl.h"  #include "llnotificationhandler.h" @@ -49,7 +47,6 @@ class LLToast;  class LLNotificationManager : public LLSingleton<LLNotificationManager>  {  	typedef std::pair<std::string, LLEventHandler*> eventhandlers; -	typedef std::pair<const std::string, LLBoundListener> listener_pair_t;  public:	  	LLNotificationManager();	  	virtual ~LLNotificationManager(); @@ -59,22 +56,12 @@ public:  	void init(void);  	//TODO: combine processing and storage (*) -	// this method reacts on system notifications and calls an appropriate handler -	bool onNotification(const LLSD& notification); -  	// this method reacts on chat notifications and calls an appropriate handler  	void onChat(const LLChat& msg, const LLSD &args); -	// get a handler for a certain type of notification -	LLEventHandler* getHandlerForNotification(std::string notification_type); - -  private: -	//TODO (*) -	std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers; -	// cruft std::map<std::string, LLChatHandler*> mChatHandlers; - -	std::map<std::string, LLBoundListener> mChannelListeners; +	boost::shared_ptr<class LLNearbyChatHandler> mChatHandler; +	std::vector<LLNotificationChannelPtr> mChannels;  };  } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 1552ed3346..6e641575fa 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -40,16 +40,14 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLOfferHandler::LLOfferHandler(e_notification_type type, const LLSD& id) +LLOfferHandler::LLOfferHandler() +:	LLSysHandler("Offer", "offer")  { -	mType = type; -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{  		channel->setControlHovering(true); -		channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -68,147 +66,109 @@ void LLOfferHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLOfferHandler::processNotification(const LLSD& notify) +bool LLOfferHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{ +	if( notification->getPayload().has("give_inventory_notification") +		&& notification->getPayload()["give_inventory_notification"].asBoolean() == false) +	{ +		// This is an original inventory offer, so add a script floater +		LLScriptFloaterManager::instance().onAddNotification(notification->getID()); +	} +	else +	{ +		bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); -		if( notification->getPayload().has("give_inventory_notification") -			&& !notification->getPayload()["give_inventory_notification"] ) +		if (add_notif_to_im)  		{ -			// This is an original inventory offer, so add a script floater -			LLScriptFloaterManager::instance().onAddNotification(notification->getID()); +			const std::string name = LLHandlerUtil::getSubstitutionName(notification); + +			LLUUID from_id = notification->getPayload()["from_id"]; + +			LLHandlerUtil::spawnIMSession(name, from_id); +			LLHandlerUtil::addNotifPanelToIM(notification);  		} -		else + +		if (!notification->canShowToast())  		{ -			notification->setReusable(LLHandlerUtil::isNotificationReusable(notification)); - -			LLUUID session_id; -			if (LLHandlerUtil::canSpawnIMSession(notification)) -			{ -				const std::string name = LLHandlerUtil::getSubstitutionName(notification); - -				LLUUID from_id = notification->getPayload()["from_id"]; - -				session_id = LLHandlerUtil::spawnIMSession(name, from_id); -			} - -			bool show_toast = LLHandlerUtil::canSpawnToast(notification); -			bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); -			if (add_notid_to_im) -			{ -				LLHandlerUtil::addNotifPanelToIM(notification); -			} - -			if (notification->getPayload().has("SUPPRESS_TOAST") -						&& notification->getPayload()["SUPPRESS_TOAST"]) -			{ -				LLNotificationsUtil::cancel(notification); -			} -			else if(show_toast) -			{ -				LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); -				// don't close notification on panel destroy since it will be used by IM floater -				notify_box->setCloseNotificationOnDestroy(!add_notid_to_im); -				LLToast::Params p; -				p.notif_id = notification->getID(); -				p.notification = notification; -				p.panel = notify_box; -				p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); -				// we not save offer notifications to the syswell floater that should be added to the IM floater -				p.can_be_stored = !add_notid_to_im; - -				LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -				if(channel) -					channel->addToast(p); - -				// if we not add notification to IM - add it to notification well -				if (!add_notid_to_im) -				{ -					// send a signal to the counter manager -					mNewNotificationSignal(); -				} -			} - -			if (LLHandlerUtil::canLogToIM(notification)) -			{ -				// log only to file if notif panel can be embedded to IM and IM is opened -				if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) -				{ -					LLHandlerUtil::logToIMP2P(notification, true); -				} -				else -				{ -					LLHandlerUtil::logToIMP2P(notification); -				} -			} +			LLNotificationsUtil::cancel(notification);  		} -	} -	else if (notify["sigtype"].asString() == "delete") -	{ -		if( notification->getPayload().has("give_inventory_notification") -			&& !notification->getPayload()["give_inventory_notification"] ) +		else if(!notification->canLogToIM() || !LLHandlerUtil::isIMFloaterOpened(notification))  		{ -			// Remove original inventory offer script floater -			LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); +			LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); +			LLToast::Params p; +			p.notif_id = notification->getID(); +			p.notification = notification; +			p.panel = notify_box; +			// we not save offer notifications to the syswell floater that should be added to the IM floater +			p.can_be_stored = !add_notif_to_im; + +			LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +			if(channel) +				channel->addToast(p);  		} -		else + +		if (notification->canLogToIM())  		{ -			if (LLHandlerUtil::canAddNotifPanelToIM(notification) -					&& !LLHandlerUtil::isIMFloaterOpened(notification)) -			{ -				LLHandlerUtil::decIMMesageCounter(notification); -			} -			mChannel.get()->killToastByNotificationID(notification->getID()); +			// log only to file if notif panel can be embedded to IM and IM is opened +			bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification); +			LLHandlerUtil::logToIMP2P(notification, file_only);  		}  	}  	return false;  } -//-------------------------------------------------------------------------- - -void LLOfferHandler::onDeleteToast(LLToast* toast) +/*virtual*/ void LLOfferHandler::onChange(LLNotificationPtr p)  { -	if (!LLHandlerUtil::canAddNotifPanelToIM(toast->getNotification())) +	LLToastNotifyPanel* panelp = LLToastNotifyPanel::getInstance(p->getID()); +	if (panelp)  	{ -		// send a signal to the counter manager -		mDelNotificationSignal(); +		// +		// HACK: if we're dealing with a notification embedded in IM, update it +		// otherwise remove its toast +		// +		if (dynamic_cast<LLIMToastNotifyPanel*>(panelp)) +		{ +			panelp->updateNotification(); +		} +		else +		{ +			// if notification has changed, hide it +			mChannel.get()->removeToastByNotificationID(p->getID()); +		}  	} - -	// send a signal to a listener to let him perform some action -	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list -	mNotificationIDSignal(toast->getNotificationID());  } -//-------------------------------------------------------------------------- -void LLOfferHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); -	if (notification -			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this -					// don't delete notification since it may be used by IM floater -					&& !LLHandlerUtil::canAddNotifPanelToIM(notification)) +/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +{ +	if( notification->getPayload().has("give_inventory_notification") +		&& !notification->getPayload()["give_inventory_notification"] ) +	{ +		// Remove original inventory offer script floater +		LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); +	} +	else  	{ -		LLNotifications::instance().cancel(notification); +		if (notification->canLogToIM()  +			&& notification->hasFormElements() +			&& !LLHandlerUtil::isIMFloaterOpened(notification)) +		{ +			LLHandlerUtil::decIMMesageCounter(notification); +		} +		mChannel.get()->removeToastByNotificationID(notification->getID());  	}  } + diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 398f54c6f7..5dcd84b400 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -37,21 +37,15 @@  using namespace LLNotificationsUI; -static const std::string SCRIPT_DIALOG				("ScriptDialog"); -static const std::string SCRIPT_DIALOG_GROUP		("ScriptDialogGroup"); -static const std::string SCRIPT_LOAD_URL			("LoadWebPage"); -  //-------------------------------------------------------------------------- -LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id) +LLScriptHandler::LLScriptHandler() +:	LLSysHandler("Notifications", "notify")  { -	mType = type; -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{  		channel->setControlHovering(true); -		channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -70,104 +64,76 @@ void LLScriptHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLScriptHandler::processNotification(const LLSD& notify) +bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add") +	if (notification->canLogToIM())  	{ -		if (LLHandlerUtil::canLogToIM(notification)) -		{ -			LLHandlerUtil::logToIMP2P(notification); -		} +		LLHandlerUtil::logToIMP2P(notification); +	} -		if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) -		{ -			LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); -		} -		else +	if(notification->hasFormElements() && !notification->canShowToast()) +	{ +		LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); +	} +	else +	{ +		LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + +		LLToast::Params p; +		p.notif_id = notification->getID(); +		p.notification = notification; +		p.panel = notify_box; +		p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); + +		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +		if(channel)  		{ -			LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); - -			LLToast::Params p; -			p.notif_id = notification->getID(); -			p.notification = notification; -			p.panel = notify_box;	 -			p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); - -			LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -			if(channel) -			{ -				channel->addToast(p); -			} - -			// send a signal to the counter manager -			mNewNotificationSignal(); +			channel->addToast(p);  		}  	} -	else if (notify["sigtype"].asString() == "delete") + +	return false; +} + + +void LLScriptHandler::onDelete( LLNotificationPtr notification )  	{ -		if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) +	if(notification->hasFormElements())  		{  			LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());  		}  		else  		{ -			mChannel.get()->killToastByNotificationID(notification->getID()); +			mChannel.get()->removeToastByNotificationID(notification->getID());  		}  	} -	return false; -} +  //--------------------------------------------------------------------------  void LLScriptHandler::onDeleteToast(LLToast* toast)  { -	// send a signal to the counter manager -	mDelNotificationSignal(); -  	// send a signal to a listener to let him perform some action  	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list -	mNotificationIDSignal(toast->getNotificationID()); -  	LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID()); -	if( notification &&  -		(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName()) ) +	if( notification && notification->hasFormElements())  	{  		LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());  	}  } -//-------------------------------------------------------------------------- -void LLScriptHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); - -	if (notification -			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this) -	{ -		LLNotifications::instance().cancel(notification); -	} -} - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index fb1adc7ddf..a31b95811e 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -84,9 +84,11 @@ bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& pay  	return false;  } +static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications"); +  void LLPersistentNotificationStorage::saveNotifications()  { -	// TODO - think about save optimization. +	LLFastTimer _(FTM_SAVE_NOTIFICATIONS);  	llofstream notify_file(mFileName.c_str());  	if (!notify_file.is_open()) @@ -98,10 +100,15 @@ void LLPersistentNotificationStorage::saveNotifications()  	LLSD output;  	LLSD& data = output["data"]; -	LLNotificationChannelPtr history_channel = LLNotifications::instance().getChannel("Persistent"); -	LLNotificationSet::iterator it = history_channel->begin(); +	boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent")); +	if (!history_channel) +	{ +		return; +	} -	for ( ; history_channel->end() != it; ++it) +	for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory(); +		it != end_it; +		++it)  	{  		LLNotificationPtr notification = *it; @@ -120,8 +127,11 @@ void LLPersistentNotificationStorage::saveNotifications()  	formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY);  } +static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); +  void LLPersistentNotificationStorage::loadNotifications()  { +	LLFastTimer _(FTM_LOAD_NOTIFICATIONS);  	LLResponderRegistry::registerResponders();  	LLNotifications::instance().getChannel("Persistent")-> diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index e397cfa046..a420c0d2ed 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -29,7 +29,7 @@  #include "llfloaterreg.h"  #include "llnearbychat.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llnotificationhandler.h"  #include "llnotifications.h"  #include "lltoastnotifypanel.h" @@ -41,15 +41,13 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLTipHandler::LLTipHandler(e_notification_type type, const LLSD& id) +LLTipHandler::LLTipHandler() +:	LLSysHandler("NotificationTips", "notifytip")  { -	mType = type;	 -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{ -		channel->setOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -68,102 +66,67 @@ void LLTipHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLTipHandler::processNotification(const LLSD& notify) +bool LLTipHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false;	 -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{  		// archive message in nearby chat -		if (LLHandlerUtil::canLogToNearbyChat(notification)) -		{ -			LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - -			// don't show toast if Nearby Chat is opened -			LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); -			LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); -			if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) -			{ -				return false; -			} -		} - -		std::string session_name = notification->getPayload()["SESSION_NAME"]; -		const std::string name = notification->getSubstitutions()["NAME"]; -		if (session_name.empty()) -		{ -			session_name = name; -		} -		LLUUID from_id = notification->getPayload()["from_id"]; -		if (LLHandlerUtil::canLogToIM(notification)) -		{ -			LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, -					notification->getMessage(), from_id, from_id); -		} - -		if (LLHandlerUtil::canSpawnIMSession(notification)) -		{ -			LLHandlerUtil::spawnIMSession(name, from_id); -		} +	if (notification->canLogToChat()) +	{ +		LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); -		// don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) -		if (!LLHandlerUtil::canSpawnToast(notification)) +		// don't show toast if Nearby Chat is opened +		LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); +		if (nearby_chat->isChatVisible())  		{  			return false;  		} +	} -		LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); - -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.notification = notification; -		p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); -		p.panel = notify_box; -		p.is_tip = true; -		p.can_be_stored = false; -		 -		removeExclusiveNotifications(notification); - -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); +	std::string session_name = notification->getPayload()["SESSION_NAME"]; +	const std::string name = notification->getSubstitutions()["NAME"]; +	if (session_name.empty()) +	{ +		session_name = name;  	} -	else if (notify["sigtype"].asString() == "delete") +	LLUUID from_id = notification->getPayload()["from_id"]; +	if (notification->canLogToIM())  	{ -		mChannel.get()->killToastByNotificationID(notification->getID()); +		LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, +				notification->getMessage(), from_id, from_id);  	} -	return false; -} - -//-------------------------------------------------------------------------- -void LLTipHandler::onDeleteToast(LLToast* toast) -{ -} - -//-------------------------------------------------------------------------- -void LLTipHandler::onRejectToast(const LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); +	if (notification->canLogToIM() && notification->hasFormElements()) +	{ +		LLHandlerUtil::spawnIMSession(name, from_id); +	} -	if (notification -			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this) +	if (notification->canLogToIM() && LLHandlerUtil::isIMFloaterOpened(notification))  	{ -		LLNotifications::instance().cancel(notification); +		return false;  	} + +	LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.notification = notification; +	p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); +	p.panel = notify_box; +	p.is_tip = true; +	p.can_be_stored = false; +		 +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); +	return false;  } diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 85626d8783..096e714981 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -28,6 +28,7 @@  #include "lloutputmonitorctrl.h"  // library includes  +#include "llfloaterreg.h"  #include "llui.h"  // viewer includes @@ -241,6 +242,17 @@ void LLOutputMonitorCtrl::draw()  		gl_rect_2d(0, monh, monw, 0, sColorBound, FALSE);  } +// virtual +BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) +{ +	if (mSpeakerId != gAgentID) +	{ +		LLFloaterReg::showInstance("floater_voice_volume", LLSD().with("avatar_id", mSpeakerId)); +	} + +	return TRUE; +} +  void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/)  {  	if (speaker_id.isNull() && mSpeakerId.notNull()) diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 2d23753d46..7b02e84744 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -68,6 +68,7 @@ public:  	// llview overrides  	virtual void	draw(); +	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);  	void			setPower(F32 val);  	F32				getPower(F32 val) const { return mPower; } diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 5c85ec438c..35cda14f8d 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -30,15 +30,23 @@  // library include  #include "llavatarname.h" +#include "llfiltereditor.h"  #include "llfloater.h"  #include "llfloaterreg.h"  #include "llnotificationsutil.h"  #include "llscrolllistctrl.h" +#include "llmenubutton.h"  // project include +#include "llavatarlistitem.h" +#include "llblocklist.h" +#include "llblockedlistitem.h"  #include "llfloateravatarpicker.h"  #include "llfloatersidepanelcontainer.h" +#include "llinventorylistitem.h" +#include "llinventorymodel.h"  #include "llsidetraypanelcontainer.h" +#include "llviewercontrol.h"  static LLRegisterPanelClassWrapper<LLPanelBlockedList> t_panel_blocked_list("panel_block_list_sidetray"); @@ -54,26 +62,35 @@ const std::string BLOCKED_PARAM_NAME = "blocked_to_select";  LLPanelBlockedList::LLPanelBlockedList()  :	LLPanel()  { -	mCommitCallbackRegistrar.add("Block.ClickPick",			boost::bind(&LLPanelBlockedList::onPickBtnClick, this)); -	mCommitCallbackRegistrar.add("Block.ClickBlockByName",	boost::bind(&LLPanelBlockedList::onBlockByNameClick, this)); -	mCommitCallbackRegistrar.add("Block.ClickRemove",		boost::bind(&LLPanelBlockedList::onRemoveBtnClick, this)); -} - -LLPanelBlockedList::~LLPanelBlockedList() -{ -	LLMuteList::getInstance()->removeObserver(this); +	mCommitCallbackRegistrar.add("Block.Action",	boost::bind(&LLPanelBlockedList::onCustomAction,  this, _2)); +	mEnableCallbackRegistrar.add("Block.Check",		boost::bind(&LLPanelBlockedList::isActionChecked, this, _2));  }  BOOL LLPanelBlockedList::postBuild()  { -	mBlockedList = getChild<LLScrollListCtrl>("blocked"); +	mBlockedList = getChild<LLBlockList>("blocked");  	mBlockedList->setCommitOnSelectionChange(TRUE); -	childSetCommitCallback("back", boost::bind(&LLPanelBlockedList::onBackBtnClick, this), NULL); +	switch (gSavedSettings.getU32("BlockPeopleSortOrder")) +	{ +	case E_SORT_BY_NAME: +		mBlockedList->sortByName(); +		break; + +	case E_SORT_BY_TYPE: +		mBlockedList->sortByType(); +		break; +	} + +	// Use the context menu of the Block list for the Block tab gear menu. +	LLToggleableMenu* blocked_gear_menu = mBlockedList->getContextMenu(); +	if (blocked_gear_menu) +	{ +		getChild<LLMenuButton>("blocked_gear_btn")->setMenu(blocked_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); +	} -	LLMuteList::getInstance()->addObserver(this); -	 -	refreshBlockedList(); +	getChild<LLButton>("unblock_btn")->setCommitCallback(boost::bind(&LLPanelBlockedList::unblockItem, this)); +	getChild<LLFilterEditor>("blocked_filter_input")->setCommitCallback(boost::bind(&LLPanelBlockedList::onFilterEdit, this, _2));  	return LLPanel::postBuild();  } @@ -94,78 +111,77 @@ void LLPanelBlockedList::onOpen(const LLSD& key)  void LLPanelBlockedList::selectBlocked(const LLUUID& mute_id)  { -	mBlockedList->selectByID(mute_id); +	mBlockedList->selectItemByUUID(mute_id);  }  void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect)  { -	LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD().with(BLOCKED_PARAM_NAME, idToSelect)); +	LLFloaterSidePanelContainer::showPanel("people", "panel_people", +		LLSD().with("people_panel_tab_name", "blocked_panel").with(BLOCKED_PARAM_NAME, idToSelect));  }  //////////////////////////////////////////////////////////////////////////  // Private Section  ////////////////////////////////////////////////////////////////////////// -void LLPanelBlockedList::refreshBlockedList() +void LLPanelBlockedList::updateButtons()  { -	mBlockedList->deleteAllItems(); +	bool hasSelected = NULL != mBlockedList->getSelectedItem(); +	getChildView("unblock_btn")->setEnabled(hasSelected); +} -	std::vector<LLMute> mutes = LLMuteList::getInstance()->getMutes(); -	std::vector<LLMute>::iterator it; -	for (it = mutes.begin(); it != mutes.end(); ++it) +void LLPanelBlockedList::unblockItem() +{ +	LLBlockedListItem* item = mBlockedList->getBlockedItem(); +	if (item)  	{ -		LLScrollListItem::Params item_p; -		item_p.enabled(TRUE); -		item_p.value(it->mID); // link UUID of blocked item with ScrollListItem -		item_p.columns.add().column("item_name").value(it->mName);//.type("text"); -		item_p.columns.add().column("item_type").value(it->getDisplayType());//.type("text").width(111); - -		mBlockedList->addRow(item_p, ADD_BOTTOM); +		LLMute mute(item->getUUID(), item->getName()); +		LLMuteList::instance().remove(mute);  	}  } -void LLPanelBlockedList::updateButtons() +void LLPanelBlockedList::onCustomAction(const LLSD& userdata)  { -	bool hasSelected = NULL != mBlockedList->getFirstSelected(); -	getChildView("Unblock")->setEnabled(hasSelected); -} - +	const std::string command_name = userdata.asString(); - -void LLPanelBlockedList::onBackBtnClick() -{ -	LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); -	if(parent) +	if ("block_obj_by_name" == command_name) +	{ +		blockObjectByName(); +	} +	else if ("block_res_by_name" == command_name) +	{ +		blockResidentByName(); +	} +	else if ("sort_by_name" == command_name) +	{ +		mBlockedList->sortByName(); +		gSavedSettings.setU32("BlockPeopleSortOrder", E_SORT_BY_NAME); +	} +	else if ("sort_by_type" == command_name)  	{ -		parent->openPreviousPanel(); +		mBlockedList->sortByType(); +		gSavedSettings.setU32("BlockPeopleSortOrder", E_SORT_BY_TYPE);  	}  } -void LLPanelBlockedList::onRemoveBtnClick() +BOOL LLPanelBlockedList::isActionChecked(const LLSD& userdata)  { -	std::string name = mBlockedList->getSelectedItemLabel(); -	LLUUID id = mBlockedList->getStringUUIDSelectedItem(); -	LLMute mute(id, name); -	 -	S32 last_selected = mBlockedList->getFirstSelectedIndex(); -	if (LLMuteList::getInstance()->remove(mute)) +	std::string item = userdata.asString(); +	U32 sort_order = gSavedSettings.getU32("BlockPeopleSortOrder"); + +	if ("sort_by_name" == item) +	{ +		return E_SORT_BY_NAME == sort_order; +	} +	else if ("sort_by_type" == item)  	{ -		// Above removals may rebuild this dialog. -		 -		if (last_selected == mBlockedList->getItemCount()) -		{ -			// we were on the last item, so select the last item again -			mBlockedList->selectNthItem(last_selected - 1); -		} -		else -		{ -			// else select the item after the last item previously selected -			mBlockedList->selectNthItem(last_selected); -		} +		return E_SORT_BY_TYPE == sort_order;  	} + +	return false;  } -void LLPanelBlockedList::onPickBtnClick() +void LLPanelBlockedList::blockResidentByName()  {  	const BOOL allow_multiple = FALSE;  	const BOOL close_on_select = TRUE; @@ -176,11 +192,19 @@ void LLPanelBlockedList::onPickBtnClick()  	// addDependentFloater(picker);  } -void LLPanelBlockedList::onBlockByNameClick() +void LLPanelBlockedList::blockObjectByName()  {  	LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName);  } +void LLPanelBlockedList::onFilterEdit(const std::string& search_string) +{ +	std::string filter = search_string; +	LLStringUtil::trimHead(filter); + +	mBlockedList->setNameFilter(filter); +} +  void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)  {  	if (names.empty() || ids.empty()) return; diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h index 74ad82e32d..332349dfc0 100644 --- a/indra/newview/llpanelblockedlist.h +++ b/indra/newview/llpanelblockedlist.h @@ -30,21 +30,15 @@  #include "llpanel.h"  #include "llmutelist.h"  #include "llfloater.h" -// #include <vector> -// class LLButton; -// class LLLineEditor; -// class LLMessageSystem; -// class LLUUID;  class LLAvatarName; -class LLScrollListCtrl; +class LLBlockList; -class LLPanelBlockedList -	:	public LLPanel, public LLMuteListObserver +class LLPanelBlockedList : public LLPanel  {  public:  	LLPanelBlockedList(); -	~LLPanelBlockedList(); +	~LLPanelBlockedList(){};  	virtual BOOL postBuild();  	virtual void draw(); @@ -59,25 +53,31 @@ public:  	 *			If it is LLUUID::null, nothing will be selected.  	 */  	static void showPanelAndSelect(const LLUUID& idToSelect); - -	// LLMuteListObserver callback interface implementation. -	/* virtual */ void onChange() {	refreshBlockedList();}  private: -	void refreshBlockedList(); + +	typedef enum e_sort_oder{ +		E_SORT_BY_NAME = 0, +		E_SORT_BY_TYPE = 1, +	} ESortOrder; +  	void updateButtons();  	// UI callbacks -	void onBackBtnClick(); -	void onRemoveBtnClick(); -	void onPickBtnClick(); -	void onBlockByNameClick(); +	void unblockItem(); +	void blockResidentByName(); +	void blockObjectByName(); +	void onFilterEdit(const std::string& search_string); + +	// List commnads +	void onCustomAction(const LLSD& userdata); +	BOOL isActionChecked(const LLSD& userdata);  	void callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);  	static void callbackBlockByName(const std::string& text);  private: -	LLScrollListCtrl* mBlockedList; +	LLBlockList* mBlockedList;  };  //----------------------------------------------------------------------------- diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 7a15d93181..00dd206571 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -83,6 +83,7 @@ public:  	LLTextBox		*mGroupName;  	std::string		mOwnerWarning;  	std::string		mAlreadyInGroup; +	std::string		mTooManySelected;  	bool		mConfirmedOwnerInvite;  	void (*mCloseCallback)(void* data); @@ -185,6 +186,17 @@ void LLPanelGroupInvite::impl::submitInvitations()  		role_member_pairs[item->getUUID()] = role_id;  	} +	const S32 MAX_GROUP_INVITES = 100; // Max invites per request. 100 to match server cap. +	if (role_member_pairs.size() > MAX_GROUP_INVITES) +	{ +		// Fail! +		LLSD msg; +		msg["MESSAGE"] = mTooManySelected; +		LLNotificationsUtil::add("GenericAlert", msg); +		(*mCloseCallback)(mCloseCallbackUserData); +		return; +	} +  	LLGroupMgr::getInstance()->sendGroupMemberInvites(mGroupID, role_member_pairs);  	if(already_in_group) @@ -621,6 +633,7 @@ BOOL LLPanelGroupInvite::postBuild()  	mImplementation->mOwnerWarning = getString("confirm_invite_owner_str");  	mImplementation->mAlreadyInGroup = getString("already_in_group"); +	mImplementation->mTooManySelected = getString("invite_selection_too_large");  	update(); diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index eda0749cdb..389baa86cd 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -1,31 +1,30 @@ -/**  +/**   * @file llpanelavatar.cpp   * @brief LLPanelAvatar and related class implementations   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */  #include "llviewerprecompiledheaders.h" -  #include "llfloaterreg.h"  #include "llpanelimcontrolpanel.h" @@ -39,393 +38,7 @@  #include "llavatarlist.h"  #include "llparticipantlist.h"  #include "llimview.h" -#include "llvoicechannel.h"  #include "llspeakers.h"  #include "lltrans.h" -void LLPanelChatControlPanel::onCallButtonClicked() -{ -	gIMMgr->startCall(mSessionId); -} - -void LLPanelChatControlPanel::onEndCallButtonClicked() -{ -	gIMMgr->endCall(mSessionId); -} - -void LLPanelChatControlPanel::onOpenVoiceControlsClicked() -{ -	LLFloaterReg::showInstance("voice_controls"); -} - -void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ -	if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) -	{ -		return; -	} - -	updateCallButton(); -} - -void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ -	updateButtons(new_state); -} - -void LLPanelChatControlPanel::updateCallButton() -{ -	// hide/show call button -	bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); - -	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId); -	 -	if (!session)  -	{ -		getChildView("call_btn")->setEnabled(false); -		return; -	} - -	bool session_initialized = session->mSessionInitialized; -	bool callback_enabled = session->mCallBackEnabled; - -	BOOL enable_connect = session_initialized -		&& voice_enabled -		&& callback_enabled; -	getChildView("call_btn")->setEnabled(enable_connect); -} - -void LLPanelChatControlPanel::updateButtons(LLVoiceChannel::EState state) -{ -	bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED; -	getChildView("end_call_btn_panel")->setVisible( is_call_started); -	getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started && findChild<LLView>("voice_ctrls_btn_panel")); -	getChildView("call_btn_panel")->setVisible( ! is_call_started); -	 -	getChildView("volume_ctrl_panel")->setVisible(state == LLVoiceChannel::STATE_CONNECTED); -	 -	updateCallButton(); -	 -} - -LLPanelChatControlPanel::~LLPanelChatControlPanel() -{ -	mVoiceChannelStateChangeConnection.disconnect(); -	if(LLVoiceClient::instanceExists()) -	{ -		LLVoiceClient::getInstance()->removeObserver(this); -	} -} - -BOOL LLPanelChatControlPanel::postBuild() -{ -	childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this)); -	childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this)); -	childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this)); - -	LLVoiceClient::getInstance()->addObserver(this); - -	return TRUE; -} - -void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) -{ -	//Method is called twice for AdHoc and Group chat. Second time when server init reply received -	mSessionId = session_id; -	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionId); -	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()); -	} -} - -LLPanelIMControlPanel::LLPanelIMControlPanel() -{ -} - -LLPanelIMControlPanel::~LLPanelIMControlPanel() -{ -	LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); -} - -BOOL LLPanelIMControlPanel::postBuild() -{ -	childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this)); -	childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this)); - -	childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this)); -	childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this)); -	childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this)); - -	childSetAction("mute_btn", boost::bind(&LLPanelIMControlPanel::onClickMuteVolume, this)); -	childSetAction("block_btn", boost::bind(&LLPanelIMControlPanel::onClickBlock, this)); -	childSetAction("unblock_btn", boost::bind(&LLPanelIMControlPanel::onClickUnblock, this)); -	 -	getChild<LLUICtrl>("volume_slider")->setCommitCallback(boost::bind(&LLPanelIMControlPanel::onVolumeChange, this, _2)); - -	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId())); - -	setFocusReceivedCallback(boost::bind(&LLPanelIMControlPanel::onFocusReceived, this)); -	 -	return LLPanelChatControlPanel::postBuild(); -} - -void LLPanelIMControlPanel::draw() -{ -	bool is_muted = LLMuteList::getInstance()->isMuted(mAvatarID); - -	getChild<LLUICtrl>("block_btn_panel")->setVisible(!is_muted); -	getChild<LLUICtrl>("unblock_btn_panel")->setVisible(is_muted); - -	if (getChildView("volume_ctrl_panel")->getVisible()) -	{ - -		bool is_muted_voice = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat); - -		LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); -		mute_btn->setValue( is_muted_voice ); - -		LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); -		volume_slider->setEnabled( !is_muted_voice ); - -		F32 volume; - -		if (is_muted_voice) -		{ -			// it's clearer to display their volume as zero -			volume = 0.f; -		} -		else -		{ -			// actual volume -			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); -		} -		volume_slider->setValue( (F64)volume ); -	} - -	LLPanelChatControlPanel::draw(); -} - -void LLPanelIMControlPanel::onClickMuteVolume() -{ -	// By convention, we only display and toggle voice mutes, not all mutes -	LLMuteList* mute_list = LLMuteList::getInstance(); -	bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); - -	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); -	if (!is_muted) -	{ -		mute_list->add(mute, LLMute::flagVoiceChat); -	} -	else -	{ -		mute_list->remove(mute, LLMute::flagVoiceChat); -	} -} - -void LLPanelIMControlPanel::onClickBlock() -{ -	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); -	 -	LLMuteList::getInstance()->add(mute); -} - -void LLPanelIMControlPanel::onClickUnblock() -{ -	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); - -	LLMuteList::getInstance()->remove(mute); -} - -void LLPanelIMControlPanel::onVolumeChange(const LLSD& data) -{ -	F32 volume = (F32)data.asReal(); -	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); -} - -void LLPanelIMControlPanel::onTeleportButtonClicked() -{ -	LLAvatarActions::offerTeleport(mAvatarID); -} -void LLPanelIMControlPanel::onPayButtonClicked() -{ -	LLAvatarActions::pay(mAvatarID); -} - -void LLPanelIMControlPanel::onViewProfileButtonClicked() -{ -	LLAvatarActions::showProfile(mAvatarID); -} - -void LLPanelIMControlPanel::onAddFriendButtonClicked() -{ -	LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); -	std::string full_name = avatar_icon->getFullName(); -	LLAvatarActions::requestFriendshipDialog(mAvatarID, full_name); -} - -void LLPanelIMControlPanel::onShareButtonClicked() -{ -	LLAvatarActions::share(mAvatarID); -} - -void LLPanelIMControlPanel::onFocusReceived() -{ -	// Disable all the buttons (Call, Teleport, etc) if disconnected. -	if (gDisconnected) -	{ -		setAllChildrenEnabled(FALSE); -	} -} - -void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id) -{ -	LLPanelChatControlPanel::setSessionId(session_id); - -	LLIMModel& im_model = LLIMModel::instance(); - -	LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); -	mAvatarID = im_model.getOtherParticipantID(session_id); -	LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); - -	// Disable "Add friend" button for friends. -	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID)); -	 -	// Disable "Teleport" button if friend is offline -	if(LLAvatarActions::isFriend(mAvatarID)) -	{ -		getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); -	} - -	getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID); - -	// Disable most profile buttons if the participant is -	// not really an SL avatar (e.g., an Avaline caller). -	LLIMModel::LLIMSession* im_session = -		im_model.findIMSession(session_id); -	if( im_session && !im_session->mOtherParticipantIsAvatar ) -	{ -		getChildView("view_profile_btn")->setEnabled(FALSE); -		getChildView("add_friend_btn")->setEnabled(FALSE); - -		getChildView("share_btn")->setEnabled(FALSE); -		getChildView("teleport_btn")->setEnabled(FALSE); -		getChildView("pay_btn")->setEnabled(FALSE); - -        getChild<LLTextBox>("avatar_name")->setValue(im_session->mName); -        getChild<LLTextBox>("avatar_name")->setToolTip(im_session->mName); -	} -	else -	{ -		// If the participant is an avatar, fetch the currect name -		gCacheName->get(mAvatarID, false, -			boost::bind(&LLPanelIMControlPanel::onNameCache, this, _1, _2, _3)); -	} -} - -//virtual -void LLPanelIMControlPanel::changed(U32 mask) -{ -	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID)); -	 -	// Disable "Teleport" button if friend is offline -	if(LLAvatarActions::isFriend(mAvatarID)) -	{ -		getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); -	} -} - -void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group) -{ -	if ( id == mAvatarID ) -	{ -		std::string avatar_name = full_name; -		getChild<LLTextBox>("avatar_name")->setValue(avatar_name); -		getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name); - -		bool is_linden = LLStringUtil::endsWith(full_name, " Linden"); -		getChild<LLUICtrl>("mute_btn")->setEnabled( !is_linden); -	} -} - -LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id): -mParticipantList(NULL) -{ -} - -BOOL LLPanelGroupControlPanel::postBuild() -{ -	childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this)); - -	return LLPanelChatControlPanel::postBuild(); -} - -LLPanelGroupControlPanel::~LLPanelGroupControlPanel() -{ -	delete mParticipantList; -	mParticipantList = NULL; -} - -// virtual -void LLPanelGroupControlPanel::draw() -{ -	// Need to resort the participant list if it's in sort by recent speaker order. -	if (mParticipantList) -		mParticipantList->update(); -	LLPanelChatControlPanel::draw(); -} - -void LLPanelGroupControlPanel::onGroupInfoButtonClicked() -{ -	LLGroupActions::show(mGroupID); -} - -void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata) -{ -	// TODO: Check this code when when sort order menu will be added. (EM) -	if (false && !mParticipantList) -		return; - -	std::string chosen_item = userdata.asString(); - -	if (chosen_item == "sort_name") -	{ -		mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); -	} - -} - -void LLPanelGroupControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ -	LLPanelChatControlPanel::onVoiceChannelStateChanged(old_state, new_state); -	mParticipantList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED); -} - -void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) -{ -	LLPanelChatControlPanel::setSessionId(session_id); - -	mGroupID = session_id; - -	// for group and Ad-hoc chat we need to include agent into list  -	if(!mParticipantList) -	{ -		LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id); -		mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true,false); -	} -} - - -LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id) -{ -} - -BOOL LLPanelAdHocControlPanel::postBuild() -{ -	//We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat -	return LLPanelChatControlPanel::postBuild(); -} diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index bba847b5d4..02915ec4bb 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -28,14 +28,12 @@  #define LL_LLPANELIMCONTROLPANEL_H  #include "llpanel.h" -#include "llvoicechannel.h"  #include "llcallingcard.h"  class LLParticipantList; -class LLPanelChatControlPanel  +class LLPanelChatControlPanel  	: public LLPanel -	, public LLVoiceClientStatusObserver  {  public:  	LLPanelChatControlPanel() : @@ -44,21 +42,6 @@ public:  	virtual BOOL postBuild(); -	void onCallButtonClicked(); -	void onEndCallButtonClicked(); -	void onOpenVoiceControlsClicked(); - -	// Implements LLVoiceClientStatusObserver::onChange() to enable the call -	// button when voice is available -	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); - -	virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); - -	void updateButtons(LLVoiceChannel::EState state); -	 -	// Enables/disables call button depending on voice availability -	void updateCallButton(); -  	virtual void setSessionId(const LLUUID& session_id);  	const LLUUID& getSessionId() { return mSessionId; } @@ -69,41 +52,6 @@ private:  	boost::signals2::connection mVoiceChannelStateChangeConnection;  }; - -class LLPanelIMControlPanel : public LLPanelChatControlPanel, LLFriendObserver -{ -public: -	LLPanelIMControlPanel(); -	~LLPanelIMControlPanel(); - -	BOOL postBuild(); - -	void setSessionId(const LLUUID& session_id); - -	// LLFriendObserver trigger -	virtual void changed(U32 mask); - -protected: -	void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group); - -private: -	void onViewProfileButtonClicked(); -	void onAddFriendButtonClicked(); -	void onShareButtonClicked(); -	void onTeleportButtonClicked(); -	void onPayButtonClicked(); -	void onFocusReceived(); - -	void onClickMuteVolume(); -	void onClickBlock(); -	void onClickUnblock(); -	/*virtual*/ void draw(); -	void onVolumeChange(const LLSD& data); - -	LLUUID mAvatarID; -}; - -  class LLPanelGroupControlPanel : public LLPanelChatControlPanel  {  public: @@ -121,9 +69,7 @@ protected:  	LLParticipantList* mParticipantList;  private: -	void onGroupInfoButtonClicked();  	void onSortMenuItemClicked(const LLSD& userdata); -	/*virtual*/ void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);  };  class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 68a3b6d1cd..469656c33f 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -52,6 +52,7 @@  #include "llmenubutton.h"  #include "llplacesinventorybridge.h"  #include "llplacesinventorypanel.h" +#include "llplacesfolderview.h"  #include "lltoggleablemenu.h"  #include "llviewermenu.h"  #include "llviewerregion.h" @@ -102,7 +103,7 @@ 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->getViewModelItem()->descendantsPassedFilter())  	{  		if (folder->isOpen())  		{ @@ -138,7 +139,7 @@ private:  // virtual  void LLOpenFolderByID::doFolder(LLFolderViewFolder* folder)  { -	if (folder->getListener() && folder->getListener()->getUUID() == mFolderID) +	if (folder->getViewModelItem() && static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem())->getUUID() == mFolderID)  	{  		if (!folder->isOpen())  		{ @@ -177,7 +178,7 @@ void LLLandmarksPanelObserver::changed(U32 mask)  	if (!mIsLibraryLandmarksOpen && library)  	{  		// Search for "Landmarks" folder in the Library and open it once on start up. See EXT-4827. -		const LLUUID &landmarks_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false, true); +		const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);  		if (landmarks_cat.notNull())  		{  			LLOpenFolderByID opener(landmarks_cat); @@ -247,10 +248,7 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string)  		LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView());  		if (NULL == inventory_list) continue; -		if (inventory_list->getFilter()) -		{ -			filter_list(inventory_list, string); -		} +		filter_list(inventory_list, string);  	}  	if (sFilterSubString != string) @@ -281,28 +279,21 @@ void LLLandmarksPanel::onShowOnMap()  //virtual  void LLLandmarksPanel::onShowProfile()  { -	LLFolderViewItem* cur_item = getCurSelectedItem(); +	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  	if(!cur_item)  		return; -	cur_item->getListener()->performAction(mCurrentSelectedList->getModel(),"about"); +	cur_item->performAction(mCurrentSelectedList->getModel(),"about");  }  // virtual  void LLLandmarksPanel::onTeleport()  { -	LLFolderViewItem* current_item = getCurSelectedItem(); -	if (!current_item) -	{ -		llwarns << "There are no selected list. No actions are performed." << llendl; -		return; -	} - -	LLFolderViewEventListener* listenerp = current_item->getListener(); -	if (listenerp && listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderViewModelItemInventory* view_model_item = getCurSelectedViewModelItem(); +	if (view_model_item && view_model_item->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{ -		listenerp->openItem(); +		view_model_item->openItem();  	}  } @@ -313,8 +304,7 @@ bool LLLandmarksPanel::isSingleItemSelected()  	if (mCurrentSelectedList != NULL)  	{ -		LLPlacesFolderView* root_view = -				static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()); +		LLFolderView* root_view = mCurrentSelectedList->getRootFolder();  		if (root_view->getSelectedCount() == 1)  		{ @@ -360,7 +350,7 @@ void LLLandmarksPanel::onSelectorButtonClicked()  	LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();  	if (!cur_item) return; -	LLFolderViewEventListener* listenerp = cur_item->getListener(); +	LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem());  	if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  		LLSD key; @@ -373,10 +363,7 @@ void LLLandmarksPanel::onSelectorButtonClicked()  void LLLandmarksPanel::updateShowFolderState()  { -	if (!mLandmarksInventoryPanel->getFilter()) -		return; - -	bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty(); +	bool show_all_folders =   mLandmarksInventoryPanel->getFilterSubString().empty();  	if (show_all_folders)  	{  		show_all_folders = category_has_descendents(mLandmarksInventoryPanel); @@ -417,8 +404,9 @@ void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_  bool LLLandmarksPanel::isLandmarkSelected() const   { -	LLFolderViewItem* current_item = getCurSelectedItem(); -	if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderViewModelItemInventory* current_item = getCurSelectedViewModelItem(); + +	if(current_item && current_item->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  		return true;  	} @@ -440,10 +428,10 @@ bool LLLandmarksPanel::isReceivedFolderSelected() const  void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb)  { -	LLFolderViewItem* cur_item = getCurSelectedItem(); -	if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); +	if(cur_item && cur_item->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  -		LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID(), cb); +		LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getUUID(), cb);  		if (landmark)  		{  			cb(landmark); @@ -456,6 +444,17 @@ LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const  	return mCurrentSelectedList ?  mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;  } +LLFolderViewModelItemInventory* LLLandmarksPanel::getCurSelectedViewModelItem() const +{ +	LLFolderViewItem* cur_item = getCurSelectedItem(); +	if (cur_item) +	{ +		return 	static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem()); +	} +	return NULL; +} + +  LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,  															 const std::string& tab_name,  															 const LLUUID& obj_id, @@ -466,7 +465,7 @@ LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPa  	LLFolderView* root = inventory_list->getRootFolder(); -	LLFolderViewItem* item = root->getItemByID(obj_id); +	LLFolderViewItem* item = inventory_list->getItemByID(obj_id);  	if (!item)  		return NULL; @@ -508,12 +507,12 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)  	// We have to make request to sever to get parcel_id and snaption_id.   	if(isLandmarkSelected())  	{ -		LLFolderViewItem* cur_item = getCurSelectedItem(); +		LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  		if (!cur_item) return; -		LLUUID id = cur_item->getListener()->getUUID(); +		LLUUID id = cur_item->getUUID();  		LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);  		doActionOnCurSelectedLandmark(boost::bind( -				&LLLandmarksPanel::doProcessParcelInfo, this, _1, cur_item, inv_item, parcel_data)); +				&LLLandmarksPanel::doProcessParcelInfo, this, _1, getCurSelectedItem(), inv_item, parcel_data));  	}  } @@ -543,7 +542,7 @@ void LLLandmarksPanel::initFavoritesInventoryPanel()  	mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list");  	initLandmarksPanel(mFavoritesInventoryPanel); -	mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems"); +	mFavoritesInventoryPanel->getFilter().setEmptyLookupMessage("FavoritesNoMatchingItems");  	initAccordion("tab_favorites", mFavoritesInventoryPanel, true);  } @@ -554,12 +553,7 @@ void LLLandmarksPanel::initLandmarksInventoryPanel()  	initLandmarksPanel(mLandmarksInventoryPanel); -	// Check if mLandmarksInventoryPanel is properly initialized and has a Filter created. -	// In case of a dummy widget getFilter() will return NULL. -	if (mLandmarksInventoryPanel->getFilter()) -	{ -		mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); -	} +	mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);  	// subscribe to have auto-rename functionality while creating New Folder  	mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2)); @@ -583,7 +577,7 @@ void LLLandmarksPanel::initLibraryInventoryPanel()  	initLandmarksPanel(mLibraryInventoryPanel);  	// We want to fetch only "Landmarks" category from the library. -	const LLUUID &landmarks_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false, true); +	const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);  	if (landmarks_cat.notNull())  	{  		LLInventoryModelBackgroundFetch::instance().start(landmarks_cat); @@ -595,12 +589,7 @@ void LLLandmarksPanel::initLibraryInventoryPanel()  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. -	if (!inventory_list->getFilter()) -		return; - -	inventory_list->getFilter()->setEmptyLookupMessage("PlacesNoMatchingItems"); +	inventory_list->getFilter().setEmptyLookupMessage("PlacesNoMatchingItems");  	inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);  	inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2)); @@ -665,20 +654,20 @@ void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory  {  	if (inventory_list != mFavoritesInventoryPanel)  	{ -		mFavoritesInventoryPanel->getRootFolder()->clearSelection(); +		mFavoritesInventoryPanel->clearSelection();  	}  	if (inventory_list != mLandmarksInventoryPanel)  	{ -		mLandmarksInventoryPanel->getRootFolder()->clearSelection(); +		mLandmarksInventoryPanel->clearSelection();  	}  	if (inventory_list != mMyInventoryPanel)  	{ -		mMyInventoryPanel->getRootFolder()->clearSelection(); +		mMyInventoryPanel->clearSelection();  	}  	if (inventory_list != mLibraryInventoryPanel)  	{ -		mLibraryInventoryPanel->getRootFolder()->clearSelection(); +		mLibraryInventoryPanel->clearSelection();  	}  } @@ -731,14 +720,9 @@ void LLLandmarksPanel::onActionsButtonClick()  {  	LLToggleableMenu* menu = mGearFolderMenu; -	LLFolderViewItem* cur_item = NULL;  	if(mCurrentSelectedList)  	{ -		cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem(); -		if(!cur_item) -			return; - -		LLFolderViewEventListener* listenerp = cur_item->getListener(); +		LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem();  		if(!listenerp)  			return; @@ -776,6 +760,9 @@ void LLLandmarksPanel::onTrashButtonClick() const  void LLLandmarksPanel::onAddAction(const LLSD& userdata) const  { +	LLFolderViewModelItemInventory* view_model = getCurSelectedViewModelItem(); +	LLFolderViewItem* item = getCurSelectedItem(); +  	std::string command_name = userdata.asString();  	if("add_landmark" == command_name)  	{ @@ -791,24 +778,24 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const  	}   	else if ("category" == command_name)  	{ -		LLFolderViewItem* item = getCurSelectedItem();  		if (item && mCurrentSelectedList == mLandmarksInventoryPanel)  		{ -			LLFolderViewEventListener* folder_bridge = NULL; -			if (item-> getListener()->getInventoryType() +			LLFolderViewModelItem* folder_bridge = NULL; + +			if (view_model->getInventoryType()  					== LLInventoryType::IT_LANDMARK)  			{  				// for a landmark get parent folder bridge -				folder_bridge = item->getParentFolder()->getListener(); +				folder_bridge = item->getParentFolder()->getViewModelItem();  			} -			else if (item-> getListener()->getInventoryType() +			else if (view_model->getInventoryType()  					== LLInventoryType::IT_CATEGORY)  			{  				// for a folder get its own bridge -				folder_bridge = item->getListener(); +				folder_bridge = view_model;  			} -			menu_create_inventory_item(mCurrentSelectedList->getRootFolder(), +			menu_create_inventory_item(mCurrentSelectedList,  					dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD(  							"category"), gInventory.findCategoryUUIDForType(  							LLFolderType::FT_LANDMARK)); @@ -816,7 +803,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const  		else  		{  			//in case My Landmarks tab is completely empty (thus cannot be determined as being selected) -			menu_create_inventory_item(mLandmarksInventoryPanel->getRootFolder(), NULL, LLSD("category"),  +			menu_create_inventory_item(mLandmarksInventoryPanel, NULL,  LLSD("category"),   				gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));  			if (mMyLandmarksAccordionTab) @@ -834,9 +821,9 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const  	std::string command_name = userdata.asString();      if("copy_slurl" == command_name)  	{ -    	LLFolderViewItem* cur_item = getCurSelectedItem(); +    	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  		if(cur_item) -			LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID()); +			LLLandmarkActions::copySLURLtoClipboard(cur_item->getUUID());  	}  	else if ( "paste" == command_name)  	{ @@ -848,7 +835,7 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const  	}  	else  	{ -		mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name); +		mCurrentSelectedList->doToSelected(command_name);  	}  } @@ -893,7 +880,7 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)  	{  		if(mCurrentSelectedList)  		{ -			mCurrentSelectedList->getRootFolder()->doToSelected(&gInventory, userdata); +			mCurrentSelectedList->doToSelected(userdata);  		}  	}  } @@ -915,8 +902,9 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  {  	std::string command_name = userdata.asString(); -	LLPlacesFolderView* root_folder_view = mCurrentSelectedList ? -		static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL; +	LLFolderView* root_folder_view = mCurrentSelectedList  +		? mCurrentSelectedList->getRootFolder()  +		: NULL;  	if ("collapse_all" == command_name)  	{ @@ -977,18 +965,13 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  	{  		if (!root_folder_view) return false; -		std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); +		std::set<LLFolderViewItem*> selected_uuids =    root_folder_view->getSelectionList();  		// Allow to execute the command only if it can be applied to all selected items. -		for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) +		for (std::set<LLFolderViewItem*>::const_iterator iter =    selected_uuids.begin(); iter != selected_uuids.end(); ++iter)  		{ -			LLFolderViewItem* item = root_folder_view->getItemByID(*iter); +			LLFolderViewItem* item = *iter; -			// If no item is found it might be a folder id. -			if (!item) -			{ -				item = root_folder_view->getFolderByID(*iter); -			}  			if (!item) return false;  			if (!canItemBeModified(command_name, item)) return false; @@ -1012,10 +995,10 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  		if ("show_on_map" == command_name)  		{ -			LLFolderViewItem* cur_item = root_folder_view->getCurSelectedItem(); +			LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  			if (!cur_item) return false; -			LLViewerInventoryItem* inv_item = cur_item->getInventoryItem(); +			LLViewerInventoryItem* inv_item = dynamic_cast<LLViewerInventoryItem*>(cur_item->getInventoryObject());  			if (!inv_item) return false;  			LLUUID asset_uuid = inv_item->getAssetUUID(); @@ -1049,7 +1032,7 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  	{  		if (mCurrentSelectedList)  		{ -			std::set<LLUUID> selection = mCurrentSelectedList->getRootFolder()->getSelectionList(); +			std::set<LLFolderViewItem*> selection =    mCurrentSelectedList->getRootFolder()->getSelectionList();  			if (!selection.empty())  			{  				return ( 1 == selection.size() && !LLAgentPicksInfo::getInstance()->isPickLimitReached() ); @@ -1105,27 +1088,23 @@ void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param)  	{  		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); -		std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); +		std::set<LLFolderViewItem*> selected_items =    root_folder_view->getSelectionList();  		// Iterate through selected items to find out if any of these items are in Trash  		// or all the items are in Trash category. -		for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) +		for (std::set<LLFolderViewItem*>::const_iterator iter =    selected_items.begin(); iter != selected_items.end(); ++iter)  		{ -			LLFolderViewItem* item = root_folder_view->getItemByID(*iter); +			LLFolderViewItem* item = *iter;  			// If no item is found it might be a folder id. -			if (!item) -			{ -				item = root_folder_view->getFolderByID(*iter); -			}  			if (!item) continue; -			LLFolderViewEventListener* listenerp = item->getListener(); +			LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem());  			if(!listenerp) continue;  			// Trash category itself should not be included because it can't be  			// actually restored from trash. -			are_all_items_in_trash &= listenerp->isItemInTrash() && *iter != trash_id; +			are_all_items_in_trash &= listenerp->isItemInTrash() &&    listenerp->getUUID() != trash_id;  			// If there are any selected items in Trash including the Trash category itself  			// we show "Restore Item" in context menu and hide other irrelevant items. @@ -1164,7 +1143,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold  	bool can_be_modified = false;  	// landmarks can be modified in any other accordion... -	if (item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	if (static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem())->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  		can_be_modified = true; @@ -1202,7 +1181,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold  	if (can_be_modified)  	{ -		LLFolderViewEventListener* listenerp = item->getListener(); +		LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem());  		if ("cut" == command_name)  		{ @@ -1262,8 +1241,9 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg  				LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data);  				if (item)  				{ -					LLFolderViewItem* fv_item = (mCurrentSelectedList && mCurrentSelectedList->getRootFolder()) ? -						mCurrentSelectedList->getRootFolder()->getItemByID(item->getUUID()) : NULL; +					LLFolderViewItem* fv_item = mCurrentSelectedList +						? mCurrentSelectedList->getItemByID(item->getUUID()) +						: NULL;  					if (fv_item)  					{ @@ -1391,7 +1371,7 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)  static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string)  {  	// When search is cleared, restore the old folder state. -	if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "") +	if (!inventory_list->getFilterSubString().empty() && string == "")  	{  		inventory_list->setFilterSubString(LLStringUtil::null);  		// Re-open folders that were open before @@ -1405,7 +1385,7 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin  	}  	// save current folder open state if no filter currently applied -	if (inventory_list->getRootFolder()->getFilterSubString().empty()) +	if (inventory_list->getFilterSubString().empty())  	{  		inventory_list->saveFolderState();  	} diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index b2f4e92473..aa5f69739d 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -44,6 +44,7 @@ class LLMenuGL;  class LLToggleableMenu;  class LLInventoryPanel;  class LLPlacesInventoryPanel; +class LLFolderViewModelItemInventory;  class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver  { @@ -87,6 +88,7 @@ protected:  	bool isReceivedFolderSelected() const;  	void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);  	LLFolderViewItem* getCurSelectedItem() const; +	LLFolderViewModelItemInventory* getCurSelectedViewModelItem() const;  	/**  	 * Selects item with "obj_id" in "inventory_list" and scrolls accordion diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index c11597f532..eb3877da5a 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -47,12 +47,14 @@  #include "llresmgr.h"  #include "llscrollcontainer.h"  #include "llsdserialize.h" +#include "llsdparam.h"  #include "llspinctrl.h"  #include "lltoggleablemenu.h"  #include "lltooldraganddrop.h"  #include "llviewermenu.h"  #include "llviewertexturelist.h"  #include "llsidepanelinventory.h" +#include "llfolderview.h"  const std::string FILTERS_FILENAME("filters.xml"); @@ -129,7 +131,7 @@ BOOL LLPanelMainInventory::postBuild()  	mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");  	mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this)); -	//panel->getFilter()->markDefault(); +	//panel->getFilter().markDefault();  	// Set up the default inv. panel/filter settings.  	mActivePanel = getChild<LLInventoryPanel>("All Items"); @@ -137,7 +139,7 @@ BOOL LLPanelMainInventory::postBuild()  	{  		// "All Items" is the previous only view, so it gets the InventorySortOrder  		mActivePanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER)); -		mActivePanel->getFilter()->markDefault(); +		mActivePanel->getFilter().markDefault();  		mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);  		mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2));  		mResortActivePanel = true; @@ -148,7 +150,7 @@ BOOL LLPanelMainInventory::postBuild()  		recent_items_panel->setSinceLogoff(TRUE);  		recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE);  		recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); -		recent_items_panel->getFilter()->markDefault(); +		recent_items_panel->getFilter().markDefault();  		recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2));  	} @@ -167,11 +169,14 @@ BOOL LLPanelMainInventory::postBuild()  		// Note that the "All Items" settings do not persist.  		if(recent_items_panel)  		{ -			if(savedFilterState.has(recent_items_panel->getFilter()->getName())) +			if(savedFilterState.has(recent_items_panel->getFilter().getName()))  			{  				LLSD recent_items = savedFilterState.get( -					recent_items_panel->getFilter()->getName()); -				recent_items_panel->getFilter()->fromLLSD(recent_items); +					recent_items_panel->getFilter().getName()); +				LLInventoryFilter::Params p; +				LLParamSDParser parser; +				parser.readSD(recent_items, p); +				recent_items_panel->getFilter().fromParams(p);  			}  		} @@ -208,24 +213,28 @@ LLPanelMainInventory::~LLPanelMainInventory( void )  	LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");  	if (all_items_panel)  	{ -		LLInventoryFilter* filter = all_items_panel->getFilter(); -		if (filter) +		LLSD filterState; +		LLInventoryPanel::InventoryState p; +		all_items_panel->getFilter().toParams(p.filter); +		all_items_panel->getRootViewModel().getSorter().toParams(p.sort); +		if (p.validateBlock(false))  		{ -			LLSD filterState; -			filter->toLLSD(filterState); -			filterRoot[filter->getName()] = filterState; +			LLParamSDParser().writeSD(filterState, p); +			filterRoot[all_items_panel->getName()] = filterState;  		}  	} -	LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); -	if (recent_items_panel) +	LLInventoryPanel* panel = findChild<LLInventoryPanel>("Recent Items"); +	if (panel)  	{ -		LLInventoryFilter* filter = recent_items_panel->getFilter(); -		if (filter) +		LLSD filterState; +		LLInventoryPanel::InventoryState p; +		panel->getFilter().toParams(p.filter); +		panel->getRootViewModel().getSorter().toParams(p.sort); +		if (p.validateBlock(false))  		{ -			LLSD filterState; -			filter->toLLSD(filterState); -			filterRoot[filter->getName()] = filterState; +			LLParamSDParser().writeSD(filterState, p); +			filterRoot[panel->getName()] = filterState;  		}  	} @@ -285,7 +294,7 @@ BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask)  void LLPanelMainInventory::doToSelected(const LLSD& userdata)  { -	getPanel()->getRootFolder()->doToSelected(&gInventory, userdata); +	getPanel()->doToSelected(userdata);  }  void LLPanelMainInventory::closeAllFolders() @@ -306,13 +315,14 @@ void LLPanelMainInventory::newWindow()  void LLPanelMainInventory::doCreate(const LLSD& userdata)  { -	menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata); +	reset_inventory_filter(); +	menu_create_inventory_item(getPanel(), NULL, userdata);  }  void LLPanelMainInventory::resetFilters()  {  	LLFloaterInventoryFinder *finder = getFinder(); -	getActivePanel()->getFilter()->resetDefault(); +	getActivePanel()->getFilter().resetDefault();  	if (finder)  	{  		finder->updateElementsFromFilter(); @@ -417,7 +427,7 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string )  	}  	// save current folder open state if no filter currently applied -	if (!mActivePanel->getRootFolder()->isFilterModified()) +	if (!mActivePanel->getFilter().isNotDefault())  	{  		mSavedFolderState->setApply(FALSE);  		mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -479,13 +489,13 @@ void LLPanelMainInventory::onFilterSelected()  	}  	setFilterSubString(mFilterSubString); -	LLInventoryFilter* filter = mActivePanel->getFilter(); +	LLInventoryFilter& filter = mActivePanel->getFilter();  	LLFloaterInventoryFinder *finder = getFinder();  	if (finder)  	{ -		finder->changeFilter(filter); +		finder->changeFilter(&filter);  	} -	if (filter->isActive()) +	if (filter.isActive())  	{  		// If our filter is active we may be the first thing requiring a fetch so we better start it here.  		LLInventoryModelBackgroundFetch::instance().start(); @@ -598,7 +608,7 @@ void LLPanelMainInventory::onFocusReceived()  void LLPanelMainInventory::setFilterTextFromFilter()   {  -	mFilterText = mActivePanel->getFilter()->getFilterText();  +	mFilterText = mActivePanel->getFilter().getFilterText();   }  void LLPanelMainInventory::toggleFindOptions() @@ -648,7 +658,7 @@ LLFloaterInventoryFinder* LLPanelMainInventory::getFinder()  LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) :	  	LLFloater(LLSD()),  	mPanelMainInventory(inventory_view), -	mFilter(inventory_view->getPanel()->getFilter()) +	mFilter(&inventory_view->getPanel()->getFilter())  {  	buildFromFile("floater_inventory_view_finder.xml");  	updateElementsFromFilter(); @@ -961,7 +971,7 @@ void LLPanelMainInventory::onTrashButtonClick()  void LLPanelMainInventory::onClipboardAction(const LLSD& userdata)  {  	std::string command_name = userdata.asString(); -	getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name); +	getActivePanel()->doToSelected(command_name);  }  void LLPanelMainInventory::saveTexture(const LLSD& userdata) @@ -972,7 +982,7 @@ void LLPanelMainInventory::saveTexture(const LLSD& userdata)  		return;  	} -	const LLUUID& item_id = current_item->getListener()->getUUID(); +	const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  	LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES);  	if (preview_texture)  	{ @@ -1045,7 +1055,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)  		{  			return;  		} -		const LLUUID item_id = current_item->getListener()->getUUID(); +		const LLUUID item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		LLViewerInventoryItem *item = gInventory.getItem(item_id);  		if (item)  		{ @@ -1060,7 +1070,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)  		{  			return;  		} -		current_item->getListener()->performAction(getActivePanel()->getModel(), "goto"); +		static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto");  	}  	if (command_name == "find_links") @@ -1070,17 +1080,17 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)  		{  			return;  		} -		const LLUUID& item_id = current_item->getListener()->getUUID(); -		const std::string &item_name = current_item->getListener()->getName(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); +		const std::string &item_name = current_item->getViewModelItem()->getName();  		mFilterSubString = item_name; -		LLInventoryFilter *filter = mActivePanel->getFilter(); -		filter->setFilterSubString(item_name); +		LLInventoryFilter &filter = mActivePanel->getFilter(); +		filter.setFilterSubString(item_name);  		mFilterEditor->setText(item_name);  		mFilterEditor->setFocus(TRUE); -		filter->setFilterUUID(item_id); -		filter->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); -		filter->setFilterLinks(LLInventoryFilter::FILTERLINK_ONLY_LINKS); +		filter.setFilterUUID(item_id); +		filter.setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); +		filter.setFilterLinks(LLInventoryFilter::FILTERLINK_ONLY_LINKS);  	}  } @@ -1089,11 +1099,11 @@ bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata)  	LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();  	if (current_item)   	{ -		LLViewerInventoryItem *inv_item = current_item->getInventoryItem(); +		LLViewerInventoryItem *inv_item = dynamic_cast<LLViewerInventoryItem*>(static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryObject());  		if(inv_item)  		{  			bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); -			LLInventoryType::EType curr_type = current_item->getListener()->getInventoryType(); +			LLInventoryType::EType curr_type = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryType();  			return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT);  		}  	} @@ -1110,15 +1120,14 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  		if (root)  		{  			can_delete = TRUE; -			std::set<LLUUID> selection_set = root->getSelectionList(); +			std::set<LLFolderViewItem*> selection_set = root->getSelectionList();  			if (selection_set.empty()) return FALSE; -			for (std::set<LLUUID>::iterator iter = selection_set.begin(); +			for (std::set<LLFolderViewItem*>::iterator iter =    selection_set.begin();  				 iter != selection_set.end();  				 ++iter)  			{ -				const LLUUID &item_id = (*iter); -				LLFolderViewItem *item = root->getItemByID(item_id); -				const LLFolderViewEventListener *listener = item->getListener(); +				LLFolderViewItem *item = *iter; +				const LLFolderViewModelItemInventory *listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem());  				llassert(listener);  				if (!listener) return FALSE;  				can_delete &= listener->isItemRemovable(); @@ -1136,7 +1145,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  	{  		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();  		if (!current_item) return FALSE; -		const LLUUID& item_id = current_item->getListener()->getUUID(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		const LLViewerInventoryItem *item = gInventory.getItem(item_id);  		if (item && item->getIsLinkType() && !item->getIsBrokenLink())  		{ @@ -1148,11 +1157,11 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  	if (command_name == "find_links")  	{  		LLFolderView* root = getActivePanel()->getRootFolder(); -		std::set<LLUUID> selection_set = root->getSelectionList(); +		std::set<LLFolderViewItem*> selection_set = root->getSelectionList();  		if (selection_set.size() != 1) return FALSE;  		LLFolderViewItem* current_item = root->getCurSelectedItem();  		if (!current_item) return FALSE; -		const LLUUID& item_id = current_item->getListener()->getUUID(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		const LLInventoryObject *obj = gInventory.getObject(item_id);  		if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType()))  		{ @@ -1165,7 +1174,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  	{  		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();  		if (!current_item) return FALSE; -		const LLUUID& item_id = current_item->getListener()->getUUID(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		const LLViewerInventoryItem *item = gInventory.getItem(item_id);  		if (item && item->getIsBrokenLink())  		{ diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 66c9c323cb..4a63585ed5 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -94,14 +94,14 @@ LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel()  	mInventoryPanel->setShape(inventory_placeholder_rect);  	// Set the sort order newest to oldest -	mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);	 -	mInventoryPanel->getFilter()->markDefault(); +	mInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_DATE); +	mInventoryPanel->getFilter().markDefault();  	// Set selection callback for proper update of inventory status buttons  	mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this));  	// Set up the note to display when the inbox is empty -	mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems"); +	mInventoryPanel->getFilter().setEmptyLookupMessage("InventoryInboxNoItems");  	// Hide the placeholder text  	inbox_inventory_placeholder->setVisible(FALSE); @@ -128,7 +128,6 @@ BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL dr  U32 LLPanelMarketplaceInbox::getFreshItemCount() const  { -#if SUPPORTING_FRESH_ITEM_COUNT  	//  	// NOTE: When turning this on, be sure to test the no inbox/outbox case because this code probably @@ -139,7 +138,7 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const  	if (mInventoryPanel)  	{ -		const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder(); +		LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();  		if (inbox_folder)  		{ @@ -174,9 +173,6 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const  	}  	return fresh_item_count; -#else -	return getTotalItemCount(); -#endif  }  U32 LLPanelMarketplaceInbox::getTotalItemCount() const @@ -231,7 +227,6 @@ void LLPanelMarketplaceInbox::draw()  		args["[NUM]"] = item_count_str;  		mInboxButton->setLabel(getString("InboxLabelWithArg", args)); -#if SUPPORTING_FRESH_ITEM_COUNT  		// set green text to fresh item count  		U32 fresh_item_count = getFreshItemCount();  		mFreshCountCtrl->setVisible((fresh_item_count > 0)); @@ -240,9 +235,6 @@ void LLPanelMarketplaceInbox::draw()  		{  			mFreshCountCtrl->setTextArg("[NUM]", llformat("%d", fresh_item_count));  		} -#else -		mFreshCountCtrl->setVisible(FALSE); -#endif  	}  	else  	{ diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 678e4f2843..68aefa7fb7 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -29,7 +29,8 @@  #include "llpanelmarketplaceinboxinventory.h"  #include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewitem.h" +#include "llfolderviewmodel.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llpanellandmarks.h" @@ -53,82 +54,17 @@ static LLDefaultChildRegistry::Register<LLInboxFolderViewItem> r3("inbox_folder_  //  LLInboxInventoryPanel::LLInboxInventoryPanel(const LLInboxInventoryPanel::Params& p) -	: LLInventoryPanel(p) -{ -} +:	LLInventoryPanel(p) +{}  LLInboxInventoryPanel::~LLInboxInventoryPanel() -{ -} - -// virtual -void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ -	// Determine the root folder in case specified, and -	// build the views starting with that folder. -	 -	LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false); -	 -	// leslie -- temporary HACK to work around sim not creating inbox with proper system folder type -	if (root_id.isNull()) -	{ -		std::string start_folder_name(params.start_folder()); -		 -		LLInventoryModel::cat_array_t* cats; -		LLInventoryModel::item_array_t* items; -		 -		gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items); -		 -		if (cats) -		{ -			for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it) -			{ -				LLInventoryCategory* cat = *cat_it; -				 -				if (cat->getName() == start_folder_name) -				{ -					root_id = cat->getUUID(); -					break; -				} -			} -		} -		 -		if (root_id == LLUUID::null) -		{ -			llwarns << "No category found that matches inbox inventory panel start_folder: " << start_folder_name << llendl; -		} -	} -	// leslie -- end temporary HACK -	 -	if (root_id == LLUUID::null) -	{ -		llwarns << "Inbox inventory panel has no root folder!" << llendl; -		root_id = LLUUID::generateNewID(); -	} -	 -	LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, -																	LLAssetType::AT_CATEGORY, -																	LLInventoryType::IT_CATEGORY, -																	this, -																	NULL, -																	root_id); -	 -	mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); -} +{}  LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)  {  	LLInboxFolderViewFolder::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); -	 -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -	  	params.root = mFolderRoot;  	params.listener = bridge;  	params.tool_tip = params.name; @@ -141,14 +77,6 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b  	LLInboxFolderViewItem::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -  	params.creation_date = bridge->getCreationDate();  	params.root = mFolderRoot;  	params.listener = bridge; @@ -163,26 +91,40 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b  //  LLInboxFolderViewFolder::LLInboxFolderViewFolder(const Params& p) -	: LLFolderViewFolder(p) -	, LLBadgeOwner(getHandle()) -	, mFresh(false) +:	LLFolderViewFolder(p), +	LLBadgeOwner(getHandle()), +	mFresh(false)  { -#if SUPPORTING_FRESH_ITEM_COUNT  	initBadgeParams(p.new_badge()); -#endif +} + +void LLInboxFolderViewFolder::addItem(LLFolderViewItem* item) +{ +    LLFolderViewFolder::addItem(item); + +    if(item) +    { +        LLInvFVBridge* itemBridge = static_cast<LLInvFVBridge*>(item->getViewModelItem()); +        LLFolderBridge * bridge = static_cast<LLFolderBridge *>(getViewModelItem()); +        bridge->updateHierarchyCreationDate(itemBridge->getCreationDate()); +    } + +    // Compute freshness if our parent is the root folder for the inbox +    if (mParentFolder == mRoot) +    { +        computeFreshness(); +    }  }  // virtual  void LLInboxFolderViewFolder::draw()  { -#if SUPPORTING_FRESH_ITEM_COUNT  	if (!badgeHasParent())  	{  		addBadgeToParentPanel();  	}  	setBadgeVisibility(mFresh); -#endif  	LLFolderViewFolder::draw();  } @@ -207,7 +149,7 @@ void LLInboxFolderViewFolder::computeFreshness()  	if (last_expansion_utc > 0)  	{ -		mFresh = (mCreationDate > last_expansion_utc); +		mFresh = (static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getCreationDate() > last_expansion_utc);  #if DEBUGGING_FRESHNESS  		if (mFresh) @@ -229,16 +171,6 @@ void LLInboxFolderViewFolder::deFreshify()  	gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());  } -void LLInboxFolderViewFolder::setCreationDate(time_t creation_date_utc) -{  -	mCreationDate = creation_date_utc;  - -	if (mParentFolder == mRoot) -	{ -		computeFreshness(); -	} -} -  //  // LLInboxFolderViewItem Implementation  // @@ -248,24 +180,18 @@ LLInboxFolderViewItem::LLInboxFolderViewItem(const Params& p)  	, LLBadgeOwner(getHandle())  	, mFresh(false)  { -#if SUPPORTING_FRESH_ITEM_COUNT  	initBadgeParams(p.new_badge()); -#endif  } -BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +void LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder)  { -	BOOL retval = LLFolderViewItem::addToFolder(folder, root); +	LLFolderViewItem::addToFolder(folder); -#if SUPPORTING_FRESH_ITEM_COUNT  	// Compute freshness if our parent is the root folder for the inbox  	if (mParentFolder == mRoot)  	{  		computeFreshness();  	} -#endif -	 -	return retval;  }  BOOL LLInboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) @@ -278,14 +204,12 @@ BOOL LLInboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask)  // virtual  void LLInboxFolderViewItem::draw()  { -#if SUPPORTING_FRESH_ITEM_COUNT  	if (!badgeHasParent())  	{  		addBadgeToParentPanel();  	}  	setBadgeVisibility(mFresh); -#endif  	LLFolderViewItem::draw();  } @@ -303,7 +227,7 @@ void LLInboxFolderViewItem::computeFreshness()  	if (last_expansion_utc > 0)  	{ -		mFresh = (mCreationDate > last_expansion_utc); +		mFresh = (static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getCreationDate() > last_expansion_utc);  #if DEBUGGING_FRESHNESS  		if (mFresh) diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index d6b827ee3e..c05e18c300 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -33,7 +33,6 @@  #include "llfolderviewitem.h" -#define SUPPORTING_FRESH_ITEM_COUNT	1 @@ -47,9 +46,6 @@ public:  	~LLInboxInventoryPanel();  	// virtual -	void buildFolderView(const LLInventoryPanel::Params& params); - -	// virtual  	LLFolderViewFolder * createFolderViewFolder(LLInvFVBridge * bridge);  	LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge);  }; @@ -63,13 +59,13 @@ public:  		Optional<LLBadge::Params>	new_badge;  		Params() -		: new_badge("new_badge") -		{ -		} +		:	new_badge("new_badge") +		{}  	};  	LLInboxFolderViewFolder(const Params& p); +    void addItem(LLFolderViewItem* item);  	void draw();  	void selectItem(); @@ -81,8 +77,6 @@ public:  	bool isFresh() const { return mFresh; }  protected: -	void setCreationDate(time_t creation_date_utc); -  	bool mFresh;  }; @@ -95,14 +89,13 @@ public:  		Optional<LLBadge::Params>	new_badge;  		Params() -			: new_badge("new_badge") -		{ -		} +		:	new_badge("new_badge") +		{}  	};  	LLInboxFolderViewItem(const Params& p); -	BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); +	void addToFolder(LLFolderViewFolder* folder);  	BOOL handleDoubleClick(S32 x, S32 y, MASK mask);  	void draw(); diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp deleted file mode 100644 index ff62cb23db..0000000000 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/**  - * @file llpanelmarketplaceoutboxinventory.cpp - * @brief LLOutboxInventoryPanel  class definition - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelmarketplaceoutboxinventory.h" - -#include "llfolderview.h" -#include "llfoldervieweventlistener.h" -#include "llinventorybridge.h" -#include "llinventoryfunctions.h" -#include "llpanellandmarks.h" -#include "llplacesinventorybridge.h" -#include "lltrans.h" -#include "llviewerfoldertype.h" - - -// -// statics -// - -static LLDefaultChildRegistry::Register<LLOutboxInventoryPanel> r1("outbox_inventory_panel"); -static LLDefaultChildRegistry::Register<LLOutboxFolderViewFolder> r2("outbox_folder_view_folder"); - - -// -// LLOutboxInventoryPanel Implementation -// - -LLOutboxInventoryPanel::LLOutboxInventoryPanel(const LLOutboxInventoryPanel::Params& p) -	: LLInventoryPanel(p) -{ -} - -LLOutboxInventoryPanel::~LLOutboxInventoryPanel() -{ -} - -// virtual -void LLOutboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ -	// Determine the root folder in case specified, and -	// build the views starting with that folder. -	 -	LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); -	 -	if (root_id == LLUUID::null) -	{ -		llwarns << "Outbox inventory panel has no root folder!" << llendl; -		root_id = LLUUID::generateNewID(); -	} -	 -	LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, -																	LLAssetType::AT_CATEGORY, -																	LLInventoryType::IT_CATEGORY, -																	this, -																	NULL, -																	root_id); -	 -	mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); -} - -LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) -{ -	LLOutboxFolderViewFolder::Params params; -	 -	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); -	 -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -	 -	params.root = mFolderRoot; -	params.listener = bridge; -	params.tool_tip = params.name; -	 -	return LLUICtrlFactory::create<LLOutboxFolderViewFolder>(params); -} - -LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge) -{ -	LLFolderViewItem::Params params; - -	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} - -	params.creation_date = bridge->getCreationDate(); -	params.root = mFolderRoot; -	params.listener = bridge; -	params.rect = LLRect (0, 0, 0, 0); -	params.tool_tip = params.name; - -	return LLUICtrlFactory::create<LLOutboxFolderViewItem>(params); -} - -// -// LLOutboxFolderViewFolder Implementation -// - -LLOutboxFolderViewFolder::LLOutboxFolderViewFolder(const Params& p) -	: LLFolderViewFolder(p) -{ -} - -// -// LLOutboxFolderViewItem Implementation -// - -LLOutboxFolderViewItem::LLOutboxFolderViewItem(const Params& p) -	: LLFolderViewItem(p) -{ -} - -BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) -{ -	return TRUE; -} - -void LLOutboxFolderViewItem::openItem() -{ -	// Intentionally do nothing to block attaching items from the outbox -} - -// eof diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.h b/indra/newview/llpanelmarketplaceoutboxinventory.h deleted file mode 100644 index a6c522b7c2..0000000000 --- a/indra/newview/llpanelmarketplaceoutboxinventory.h +++ /dev/null @@ -1,78 +0,0 @@ -/**  - * @file llpanelmarketplaceoutboxinventory.h - * @brief LLOutboxInventoryPanel class declaration - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_OUTBOXINVENTORYPANEL_H -#define LL_OUTBOXINVENTORYPANEL_H - - -#include "llinventorypanel.h" -#include "llfolderviewitem.h" - - -class LLOutboxInventoryPanel : public LLInventoryPanel -{ -public: -	struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params> -	{ -		Params() {} -	}; -	 -	LLOutboxInventoryPanel(const Params& p); -	~LLOutboxInventoryPanel(); - -	// virtual -	void buildFolderView(const LLInventoryPanel::Params& params); - -	// virtual -	LLFolderViewFolder *	createFolderViewFolder(LLInvFVBridge * bridge); -	LLFolderViewItem *		createFolderViewItem(LLInvFVBridge * bridge); -}; - - -class LLOutboxFolderViewFolder : public LLFolderViewFolder -{ -public: -	struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params> -	{ -		Params() {} -	}; -	 -	LLOutboxFolderViewFolder(const Params& p); -}; - - -class LLOutboxFolderViewItem : public LLFolderViewItem -{ -public: -	LLOutboxFolderViewItem(const Params& p); - -	// virtual -	BOOL handleDoubleClick(S32 x, S32 y, MASK mask); -	void openItem(); -}; - - -#endif //LL_OUTBOXINVENTORYPANEL_H diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 1ca24f3031..82956beb3d 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -71,12 +71,13 @@  /// Class LLTaskInvFVBridge  ///---------------------------------------------------------------------------- -class LLTaskInvFVBridge : public LLFolderViewEventListener +class LLTaskInvFVBridge : public LLFolderViewModelItemInventory  {  protected:  	LLUUID mUUID;  	std::string mName;  	mutable std::string mDisplayName; +	mutable std::string mSearchableName;  	LLPanelObjectInventory* mPanel;  	U32 mFlags;  	LLAssetType::EType mAssetType;	 @@ -102,26 +103,29 @@ public:  	S32 getPrice();  	static bool commitBuyItem(const LLSD& notification, const LLSD& response); -	// LLFolderViewEventListener functionality +	// LLFolderViewModelItemInventory functionality  	virtual const std::string& getName() const;  	virtual const std::string& getDisplayName() const; +	virtual const std::string& getSearchableName() const; +  	virtual PermissionMask getPermissionMask() const { return PERM_NONE; }  	/*virtual*/ LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; }  	virtual const LLUUID& getUUID() const { return mUUID; }  	virtual time_t getCreationDate() const; +	virtual void setCreationDate(time_t creation_date_utc); +  	virtual LLUIImagePtr getIcon() const;  	virtual void openItem();  	virtual BOOL canOpenItem() const { return FALSE; }  	virtual void closeItem() {} -	virtual void previewItem();  	virtual void selectItem() {}  	virtual BOOL isItemRenameable() const;  	virtual BOOL renameItem(const std::string& new_name);  	virtual BOOL isItemMovable() const;  	virtual BOOL isItemRemovable() const;  	virtual BOOL removeItem(); -	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); -	virtual void move(LLFolderViewEventListener* parent_listener); +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); +	virtual void move(LLFolderViewModelItem* parent_listener);	  	virtual BOOL isItemCopyable() const;  	virtual BOOL copyToClipboard() const;  	virtual BOOL cutToClipboard() const; @@ -131,11 +135,15 @@ public:  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  	virtual void performAction(LLInventoryModel* model, std::string action);  	virtual BOOL isUpToDate() const { return TRUE; } -	virtual BOOL hasChildren() const { return FALSE; } +	virtual bool hasChildren() const { return FALSE; }  	virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; }  	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } +	virtual EInventorySortGroup getSortGroup() const { return SG_ITEM; } +	virtual LLInventoryObject* getInventoryObject() const { return findInvObject(); } +  	// LLDragAndDropBridge functionality +	virtual LLToolDragAndDrop::ESource getDragSource() const { return LLToolDragAndDrop::SOURCE_WORLD; }  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type, @@ -147,7 +155,8 @@ LLTaskInvFVBridge::LLTaskInvFVBridge(  	LLPanelObjectInventory* panel,  	const LLUUID& uuid,  	const std::string& name, -	U32 flags): +	U32 flags) +:	LLFolderViewModelItemInventory(panel->getRootViewModel()),  	mUUID(uuid),  	mName(name),  	mPanel(panel), @@ -330,15 +339,27 @@ const std::string& LLTaskInvFVBridge::getDisplayName() const  		}  	} +	mSearchableName.assign(mDisplayName + getLabelSuffix()); +  	return mDisplayName;  } +const std::string& LLTaskInvFVBridge::getSearchableName() const +{ +	return mSearchableName; +} + +  // BUG: No creation dates for task inventory  time_t LLTaskInvFVBridge::getCreationDate() const  {  	return 0;  } +void LLTaskInvFVBridge::setCreationDate(time_t creation_date_utc) +{} + +  LLUIImagePtr LLTaskInvFVBridge::getIcon() const  {  	const BOOL item_is_multi = (mFlags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS); @@ -352,11 +373,6 @@ void LLTaskInvFVBridge::openItem()  	lldebugs << "LLTaskInvFVBridge::openItem()" << llendl;  } -void LLTaskInvFVBridge::previewItem() -{ -	openItem(); -} -  BOOL LLTaskInvFVBridge::isItemRenameable() const  {  	if(gAgent.isGodlike()) return TRUE; @@ -467,7 +483,7 @@ BOOL LLTaskInvFVBridge::removeItem()  	return FALSE;  } -void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void   LLTaskInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch)  {  	if (!mPanel)  	{ @@ -507,7 +523,7 @@ void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>&  	}  } -void LLTaskInvFVBridge::move(LLFolderViewEventListener* parent_listener) +void LLTaskInvFVBridge::move(LLFolderViewModelItem* parent_listener)  {  } @@ -709,7 +725,7 @@ public:  	virtual BOOL renameItem(const std::string& new_name);  	virtual BOOL isItemRemovable() const;  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags); -	virtual BOOL hasChildren() const; +	virtual bool hasChildren() const;  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type, @@ -717,6 +733,7 @@ public:  							std::string& tooltip_msg);  	virtual BOOL canOpenItem() const { return TRUE; }  	virtual void openItem(); +	virtual EInventorySortGroup getSortGroup() const { return SG_NORMAL_FOLDER; }  };  LLTaskCategoryBridge::LLTaskCategoryBridge( @@ -739,15 +756,7 @@ const std::string& LLTaskCategoryBridge::getDisplayName() const  	if (cat)  	{ -		// Localize "Contents" folder. -		if (cat->getParentUUID().isNull() && cat->getName() == "Contents") -		{ -			mDisplayName.assign(LLTrans::getString("ViewerObjectContents")); -		} -		else -		{ -			mDisplayName.assign(cat->getName()); -		} +		mDisplayName.assign(cat->getName());  	}  	return mDisplayName; @@ -775,7 +784,7 @@ void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  	hide_context_entries(menu, items, disabled_items);  } -BOOL LLTaskCategoryBridge::hasChildren() const +bool LLTaskCategoryBridge::hasChildren() const  {  	// return TRUE if we have or do know know if we have children.  	// *FIX: For now, return FALSE - we will know for sure soon enough. @@ -1514,7 +1523,7 @@ BOOL LLPanelObjectInventory::postBuild()  void LLPanelObjectInventory::doToSelected(const LLSD& userdata)  { -	mFolders->doToSelected(&gInventory, userdata); +	LLInventoryAction::doToSelected(&gInventory, mFolders, userdata.asString());  }  void LLPanelObjectInventory::clearContents() @@ -1526,6 +1535,8 @@ void LLPanelObjectInventory::clearContents()  		LLToolDragAndDrop::getInstance()->endDrag();  	} +	clearItemIDs(); +  	if( mScroller )  	{  		// removes mFolders @@ -1541,21 +1552,24 @@ void LLPanelObjectInventory::reset()  {  	clearContents(); -	//setBorderVisible(FALSE); -	  	mCommitCallbackRegistrar.pushScope(); // push local callbacks  	LLRect dummy_rect(0, 1, 1, 0);  	LLFolderView::Params p;  	p.name = "task inventory";  	p.title = "task inventory"; -	p.task_id = getTaskUUID();  	p.parent_panel = this;  	p.tool_tip= LLTrans::getString("PanelContentsTooltip");  	p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); +	p.folder_indentation = -14; // subtract space normally reserved for folder expanders +	p.view_model = &mInventoryViewModel; +	p.root = NULL;  	mFolders = LLUICtrlFactory::create<LLFolderView>(p);  	// this ensures that we never say "searching..." or "no items found" -	mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); +	//TODO RN: make this happen by manipulating filter object directly +  	LLInventoryFilter& inventoryFilter = dynamic_cast<LLInventoryFilter&>(mFolders->getFolderViewModel()->getFilter()); +   	inventoryFilter.setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); +    	mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);  	if (hasFocus()) @@ -1600,7 +1614,7 @@ void LLPanelObjectInventory::inventoryChanged(LLViewerObject* object,  			 iter != inventory->end(); )  		{  			LLInventoryObject* item = *iter++; -			LLFloaterProperties* floater = LLFloaterReg::findTypedInstance<LLFloaterProperties>("properites", item->getUUID()); +			LLFloaterProperties* floater = LLFloaterReg::findTypedInstance<LLFloaterProperties>("properties", item->getUUID());  			if(floater)  			{  				floater->refresh(); @@ -1615,15 +1629,20 @@ void LLPanelObjectInventory::updateInventory()  	//		<< " panel UUID: " << panel->mTaskUUID << "\n"  	//		<< " task  UUID: " << object->mID << llendl;  	// We're still interested in this task's inventory. -	std::set<LLUUID> selected_items; +	std::vector<LLUUID> selected_item_ids; +	std::set<LLFolderViewItem*> selected_items;  	BOOL inventory_has_focus = FALSE; -	if (mHaveInventory) +	if (mHaveInventory && mFolders)  	{  		selected_items = mFolders->getSelectionList();  		inventory_has_focus = gFocusMgr.childHasKeyboardFocus(mFolders);  	} - -	reset(); +	for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(), end_it = selected_items.end(); +		it != end_it; +		++it) +	{ +		selected_item_ids.push_back(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +	}  	LLViewerObject* objectp = gObjectList.findObject(mTaskUUID);  	if (objectp) @@ -1631,19 +1650,21 @@ void LLPanelObjectInventory::updateInventory()  		LLInventoryObject* inventory_root = objectp->getInventoryRoot();  		LLInventoryObject::object_list_t contents;  		objectp->getInventoryContents(contents); +  		if (inventory_root)  		{ -			createFolderViews(inventory_root, contents); -			mHaveInventory = TRUE; +			reset();  			mIsInventoryEmpty = FALSE; +			createFolderViews(inventory_root, contents);  			mFolders->setEnabled(TRUE);  		}  		else  		{  			// TODO: create an empty inventory  			mIsInventoryEmpty = TRUE; -			mHaveInventory = TRUE;  		} + +		mHaveInventory = TRUE;  	}  	else  	{ @@ -1653,11 +1674,12 @@ void LLPanelObjectInventory::updateInventory()  	}  	// restore previous selection -	std::set<LLUUID>::iterator selection_it; -	BOOL first_item = TRUE; -	for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) +	std::vector<LLUUID>::iterator selection_it; +	bool first_item = true; +	for (selection_it = selected_item_ids.begin(); selection_it != selected_item_ids.end(); ++selection_it)  	{ -		LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it); +		LLFolderViewItem* selected_item = getItemByID(*selection_it); +		  		if (selected_item)  		{  			//HACK: "set" first item then "change" each other one to get keyboard focus right @@ -1673,7 +1695,10 @@ void LLPanelObjectInventory::updateInventory()  		}  	} -	mFolders->requestArrange(); +	if (mFolders) +	{ +		mFolders->requestArrange(); +	}  	mInventoryNeedsUpdate = FALSE;  	// Edit menu handler is set in onFocusReceived  } @@ -1694,19 +1719,20 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root  	bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root);  	if(bridge)  	{ -		LLFolderViewFolder* new_folder = NULL;  		LLFolderViewFolder::Params p;  		p.name = inventory_root->getName(); -		p.icon = LLUI::getUIImage("Inv_FolderClosed"); -		p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); +		p.tool_tip = p.name;  		p.root = mFolders;  		p.listener = bridge; -		p.tool_tip = p.name; -		new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); -		new_folder->addToFolder(mFolders, mFolders); + +		LLFolderViewFolder* new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); +		new_folder->addToFolder(mFolders);  		new_folder->toggleOpen(); -		createViewsForCategory(&contents, inventory_root, new_folder); +		if (!contents.empty()) +		{ +			createViewsForCategory(&contents, inventory_root, new_folder); +		}  	}  } @@ -1738,8 +1764,6 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  			{  				LLFolderViewFolder::Params p;  				p.name = obj->getName(); -				p.icon = LLUI::getUIImage("Inv_FolderClosed"); -				p.icon_open = LLUI::getUIImage("Inv_FolderOpen");  				p.root = mFolders;  				p.listener = bridge;  				p.tool_tip = p.name; @@ -1751,7 +1775,6 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  			{  				LLFolderViewItem::Params params;  				params.name(obj->getName()); -				params.icon(bridge->getIcon());  				params.creation_date(bridge->getCreationDate());  				params.root(mFolders);  				params.listener(bridge); @@ -1759,7 +1782,8 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  				params.tool_tip = params.name;  				view = LLUICtrlFactory::create<LLFolderViewItem> (params);  			} -			view->addToFolder(folder, mFolders); +			view->addToFolder(folder); +			addItemID(obj->getUUID(), view);  		}  	} @@ -1827,6 +1851,7 @@ void LLPanelObjectInventory::refresh()  		removeVOInventoryListener();  		clearContents();  	} +	mInventoryViewModel.setTaskID(mTaskUUID);  	//llinfos << "LLPanelObjectInventory::refresh() " << mTaskUUID << llendl;  } @@ -1914,7 +1939,10 @@ void LLPanelObjectInventory::idle(void* user_data)  {  	LLPanelObjectInventory* self = (LLPanelObjectInventory*)user_data; - +	if (self->mFolders) +	{ +		self->mFolders->update(); +	}  	if (self->mInventoryNeedsUpdate)  	{  		self->updateInventory(); @@ -1939,3 +1967,32 @@ void LLPanelObjectInventory::onFocusReceived()  	LLPanel::onFocusReceived();  } + + +LLFolderViewItem* LLPanelObjectInventory::getItemByID( const LLUUID& id ) +{ +	std::map<LLUUID, LLFolderViewItem*>::iterator map_it; +	map_it = mItemMap.find(id); +	if (map_it != mItemMap.end()) +	{ +		return map_it->second; +	} + +	return NULL; +} + +void LLPanelObjectInventory::removeItemID( const LLUUID& id ) +{ +	mItemMap.erase(id); +} + +void LLPanelObjectInventory::addItemID( const LLUUID& id, LLFolderViewItem* itemp ) +{ +	mItemMap[id] = itemp; +} + +void LLPanelObjectInventory::clearItemIDs() +{ +	mItemMap.clear(); +} + diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 607b705f7f..f497c695b3 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -29,6 +29,7 @@  #include "llvoinventorylistener.h"  #include "llpanel.h" +#include "llinventorypanel.h" // for LLFolderViewModelInventory  #include "llinventory.h" @@ -55,6 +56,8 @@ public:  	virtual BOOL postBuild(); +	LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; } +  	void doToSelected(const LLSD& userdata);  	void refresh(); @@ -85,8 +88,15 @@ protected:  								LLInventoryObject* parent,  								LLFolderViewFolder* folder);  	void clearContents(); +	LLFolderViewItem* getItemByID(const LLUUID& id); + +	void addItemID( const LLUUID& id, LLFolderViewItem*   itemp ); +	void removeItemID(const LLUUID& id); +	void clearItemIDs();  private: +	std::map<LLUUID, LLFolderViewItem*> mItemMap; +  	LLScrollContainer* mScroller;  	LLFolderView* mFolders; @@ -94,6 +104,7 @@ private:  	BOOL mHaveInventory;  	BOOL mIsInventoryEmpty;  	BOOL mInventoryNeedsUpdate; +	LLFolderViewModelInventory	mInventoryViewModel;	  };  #endif // LL_LLPANELOBJECTINVENTORY_H diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 35e2e96bab..d690a18477 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -270,7 +270,7 @@ private:  		if (inventory_panel->getVisible())  		{ -			inventory_panel->setSortOrder(sort_order); +			inventory_panel->getFolderViewModel()->setSorter(sort_order);  		}  		else  		{ @@ -738,7 +738,7 @@ void LLPanelOutfitEdit::onSearchEdit(const std::string& string)  	}  	// save current folder open state if no filter currently applied -	if (mInventoryItemsPanel->getRootFolder()->getFilterSubString().empty()) +	if (mInventoryItemsPanel->getFilterSubString().empty())  	{  		mSavedFolderState->setApply(FALSE);  		mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -885,13 +885,13 @@ LLPanelOutfitEdit::selection_info_t LLPanelOutfitEdit::getAddMorePanelSelectionT  	{  		if (mInventoryItemsPanel != NULL && mInventoryItemsPanel->getVisible())  		{ -			std::set<LLUUID> selected_uuids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); +			std::set<LLFolderViewItem*> selected_items =    mInventoryItemsPanel->getRootFolder()->getSelectionList(); -			result.second = selected_uuids.size(); +			result.second = selected_items.size();  			if (result.second == 1)  			{ -				result.first = getWearableTypeByItemUUID(*(selected_uuids.begin())); +				result.first = getWearableTypeByItemUUID(static_cast<LLFolderViewModelItemInventory*>((*selected_items.begin())->getViewModelItem())->getUUID());  			}  		}  		else if (mWearableItemsList != NULL && mWearableItemsList->getVisible()) @@ -1310,7 +1310,7 @@ void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id)  		LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem();  		if (!curr_item) return; -		LLFolderViewEventListener* listenerp  = curr_item->getListener(); +		LLFolderViewModelItemInventory* listenerp  = static_cast<LLFolderViewModelItemInventory*>(curr_item->getViewModelItem());  		if (!listenerp) return;  		selected_id = listenerp->getUUID(); @@ -1327,9 +1327,13 @@ void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list)  	void (uuid_vec_t::* tmp)(LLUUID const &) = &uuid_vec_t::push_back;  	if (mInventoryItemsPanel->getVisible())  	{ -		std::set<LLUUID> item_set = mInventoryItemsPanel->getRootFolder()->getSelectionList(); - -		std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, _1)); +		std::set<LLFolderViewItem*> item_set =    mInventoryItemsPanel->getRootFolder()->getSelectionList(); +		for (std::set<LLFolderViewItem*>::iterator it = item_set.begin(),    end_it = item_set.end(); +			it != end_it; +			++it) +		{ +			uuid_list.push_back(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +		}  	}  	else if (mWearablesListViewPanel->getVisible())  	{ @@ -1374,13 +1378,13 @@ void LLPanelOutfitEdit::saveListSelection()  {  	if(mWearablesListViewPanel->getVisible())  	{ -		std::set<LLUUID> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); +		std::set<LLFolderViewItem*> selected_ids =    mInventoryItemsPanel->getRootFolder()->getSelectionList();  		if(!selected_ids.size()) return; -		for (std::set<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) +		for (std::set<LLFolderViewItem*>::const_iterator item_id =    selected_ids.begin(); item_id != selected_ids.end(); ++item_id)  		{ -			mWearableItemsList->selectItemByUUID(*item_id, true); +			mWearableItemsList->selectItemByUUID(static_cast<LLFolderViewModelItemInventory*>((*item_id)->getViewModelItem())->getUUID(),    true);  		}  		mWearableItemsList->scrollToShowFirstSelectedItem();  	} @@ -1398,7 +1402,7 @@ void LLPanelOutfitEdit::saveListSelection()  		for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id)  		{ -			LLFolderViewItem* item = root->getItemByID(*item_id); +			LLFolderViewItem* item = mInventoryItemsPanel->getItemByID(*item_id);  			if (!item) continue;  			LLFolderViewFolder* parent = item->getParentFolder(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index f1380e7a36..260de40eef 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -72,6 +72,7 @@ static const std::string NEARBY_TAB_NAME	= "nearby_panel";  static const std::string FRIENDS_TAB_NAME	= "friends_panel";  static const std::string GROUP_TAB_NAME		= "groups_panel";  static const std::string RECENT_TAB_NAME	= "recent_panel"; +static const std::string BLOCKED_TAB_NAME	= "blocked_panel"; // blocked avatars  static const std::string COLLAPSED_BY_USER  = "collapsed_by_user"; @@ -492,26 +493,37 @@ public:  LLPanelPeople::LLPanelPeople()  	:	LLPanel(), -		mFilterSubString(LLStringUtil::null), -		mFilterSubStringOrig(LLStringUtil::null), -		mFilterEditor(NULL),  		mTabContainer(NULL),  		mOnlineFriendList(NULL),  		mAllFriendList(NULL),  		mNearbyList(NULL),  		mRecentList(NULL),  		mGroupList(NULL), -		mNearbyGearButton(NULL), -		mFriendsGearButton(NULL), -		mGroupsGearButton(NULL), -		mRecentGearButton(NULL),  		mMiniMap(NULL)  {  	mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList,	this));  	mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList,	this));  	mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList,	this));  	mButtonsUpdater = new LLButtonsUpdater(boost::bind(&LLPanelPeople::updateButtons, this)); -	mCommitCallbackRegistrar.add("People.addFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); + +	mCommitCallbackRegistrar.add("People.AddFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); +	mCommitCallbackRegistrar.add("People.AddFriendWizard",	boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked,	this)); +	mCommitCallbackRegistrar.add("People.DelFriend",		boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked,	this)); +	mCommitCallbackRegistrar.add("People.Group.Minus",		boost::bind(&LLPanelPeople::onGroupMinusButtonClicked,  this)); +	mCommitCallbackRegistrar.add("People.Chat",			boost::bind(&LLPanelPeople::onChatButtonClicked,		this)); +	mCommitCallbackRegistrar.add("People.Gear",			boost::bind(&LLPanelPeople::onGearButtonClicked,		this, _1)); + +	mCommitCallbackRegistrar.add("People.Group.Plus.Action",  boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Friends.ViewSort.Action",  boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Nearby.ViewSort.Action",  boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Groups.ViewSort.Action",  boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Recent.ViewSort.Action",  boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked,  this, _2)); + +	mEnableCallbackRegistrar.add("People.Friends.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck,	this, _2)); +	mEnableCallbackRegistrar.add("People.Recent.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck,	this, _2)); +	mEnableCallbackRegistrar.add("People.Nearby.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck,	this, _2)); + +	mEnableCallbackRegistrar.add("People.Group.Plus.Validate",	boost::bind(&LLPanelPeople::onGroupPlusButtonValidate,	this));  }  LLPanelPeople::~LLPanelPeople() @@ -525,13 +537,6 @@ LLPanelPeople::~LLPanelPeople()  	{  		LLVoiceClient::getInstance()->removeObserver(this);  	} - -	if (mGroupPlusMenuHandle.get()) mGroupPlusMenuHandle.get()->die(); -	if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); -	if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); -	if (mGroupsViewSortMenuHandle.get()) mGroupsViewSortMenuHandle.get()->die(); -	if (mRecentViewSortMenuHandle.get()) mRecentViewSortMenuHandle.get()->die(); -  }  void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list) @@ -553,11 +558,15 @@ void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LL  BOOL LLPanelPeople::postBuild()  { -	mFilterEditor = getChild<LLFilterEditor>("filter_input"); -	mFilterEditor->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("nearby_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("friends_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));  	mTabContainer = getChild<LLTabContainer>("tabs");  	mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2)); +	mSavedFilters.resize(mTabContainer->getTabCount()); +	mSavedOriginalFilters.resize(mTabContainer->getTabCount());  	LLPanel* friends_tab = getChild<LLPanel>(FRIENDS_TAB_NAME);  	// updater is active only if panel is visible to user. @@ -601,14 +610,6 @@ BOOL LLPanelPeople::postBuild()  	setSortOrder(mAllFriendList,	(ESortOrder)gSavedSettings.getU32("FriendsSortOrder"),		false);  	setSortOrder(mNearbyList,		(ESortOrder)gSavedSettings.getU32("NearbyPeopleSortOrder"),	false); -	LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME); -	groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked,	this)); -	groups_panel->childSetAction("plus_btn",	boost::bind(&LLPanelPeople::onGroupPlusButtonClicked,	this)); - -	LLPanel* friends_panel = getChild<LLPanel>(FRIENDS_TAB_NAME); -	friends_panel->childSetAction("add_btn",	boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked,	this)); -	friends_panel->childSetAction("del_btn",	boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked,	this)); -  	mOnlineFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));  	mAllFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));  	mNearbyList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); @@ -629,6 +630,19 @@ BOOL LLPanelPeople::postBuild()  	mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this));  	mGroupList->setReturnCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this)); +	LLMenuButton* groups_gear_btn = getChild<LLMenuButton>("groups_gear_btn"); + +	// Use the context menu of the Groups list for the Groups tab gear menu. +	LLToggleableMenu* groups_gear_menu = mGroupList->getContextMenu(); +	if (groups_gear_menu) +	{ +		groups_gear_btn->setMenu(groups_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); +	} +	else +	{ +		llwarns << "People->Groups list menu not found" << llendl; +	} +  	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>("tab_all");  	accordion_tab->setDropDownStateChangedCallback(  		boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mAllFriendList)); @@ -637,70 +651,9 @@ BOOL LLPanelPeople::postBuild()  	accordion_tab->setDropDownStateChangedCallback(  		boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mOnlineFriendList)); -	buttonSetAction("view_profile_btn",	boost::bind(&LLPanelPeople::onViewProfileButtonClicked,	this)); -	buttonSetAction("group_info_btn",	boost::bind(&LLPanelPeople::onGroupInfoButtonClicked,	this)); -	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)); -  	// Must go after setting commit callback and initializing all pointers to children.  	mTabContainer->selectTabByName(NEARBY_TAB_NAME); -	// Create menus. -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; -	 -	registrar.add("People.Group.Plus.Action",  boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked,  this, _2)); -	registrar.add("People.Group.Minus.Action", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked,  this)); -	registrar.add("People.Friends.ViewSort.Action",  boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked,  this, _2)); -	registrar.add("People.Nearby.ViewSort.Action",  boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked,  this, _2)); -	registrar.add("People.Groups.ViewSort.Action",  boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked,  this, _2)); -	registrar.add("People.Recent.ViewSort.Action",  boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked,  this, _2)); - -	enable_registrar.add("People.Group.Minus.Enable",	boost::bind(&LLPanelPeople::isRealGroup,	this)); -	enable_registrar.add("People.Friends.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck,	this, _2)); -	enable_registrar.add("People.Recent.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck,	this, _2)); -	enable_registrar.add("People.Nearby.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck,	this, _2)); - -	mNearbyGearButton = getChild<LLMenuButton>("nearby_view_sort_btn"); -	mFriendsGearButton = getChild<LLMenuButton>("friends_viewsort_btn"); -	mGroupsGearButton = getChild<LLMenuButton>("groups_viewsort_btn"); -	mRecentGearButton = getChild<LLMenuButton>("recent_viewsort_btn"); - -	LLMenuGL* plus_menu  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	mGroupPlusMenuHandle  = plus_menu->getHandle(); - -	LLToggleableMenu* nearby_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_nearby_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(nearby_view_sort) -	{ -		mNearbyViewSortMenuHandle  = nearby_view_sort->getHandle(); -		mNearbyGearButton->setMenu(nearby_view_sort); -	} - -	LLToggleableMenu* friend_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_friends_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(friend_view_sort) -	{ -		mFriendsViewSortMenuHandle  = friend_view_sort->getHandle(); -		mFriendsGearButton->setMenu(friend_view_sort); -	} - -	LLToggleableMenu* group_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(group_view_sort) -	{ -		mGroupsViewSortMenuHandle  = group_view_sort->getHandle(); -		mGroupsGearButton->setMenu(group_view_sort); -	} - -	LLToggleableMenu* recent_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_recent_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(recent_view_sort) -	{ -		mRecentViewSortMenuHandle  = recent_view_sort->getHandle(); -		mRecentGearButton->setMenu(recent_view_sort); -	} -  	LLVoiceClient::getInstance()->addObserver(this);  	// call this method in case some list is empty and buttons can be in inconsistent state @@ -735,9 +688,11 @@ void LLPanelPeople::updateFriendListHelpText()  	if (no_friends_text->getVisible())  	{  		//update help text for empty lists -		std::string message_name = mFilterSubString.empty() ? "no_friends_msg" : "no_filtered_friends_msg"; +		const std::string& filter = mSavedOriginalFilters[mTabContainer->getCurrentPanelIndex()]; + +		std::string message_name = filter.empty() ? "no_friends_msg" : "no_filtered_friends_msg";  		LLStringUtil::format_map_t args; -		args["[SEARCH_TERM]"] = LLURI::escape(mFilterSubStringOrig); +		args["[SEARCH_TERM]"] = LLURI::escape(filter);  		no_friends_text->setText(getString(message_name, args));  	}  } @@ -821,31 +776,9 @@ void LLPanelPeople::updateRecentList()  	mRecentList->setDirty();  } -void LLPanelPeople::buttonSetVisible(std::string btn_name, BOOL visible) -{ -	// To make sure we're referencing the right widget (a child of the button bar). -	LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); -	button->setVisible(visible); -} - -void LLPanelPeople::buttonSetEnabled(const std::string& btn_name, bool enabled) -{ -	// To make sure we're referencing the right widget (a child of the button bar). -	LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); -	button->setEnabled(enabled); -} - -void LLPanelPeople::buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb) -{ -	// To make sure we're referencing the right widget (a child of the button bar). -	LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); -	button->setClickedCallback(cb); -} -  void LLPanelPeople::updateButtons()  {  	std::string cur_tab		= getActiveTabName(); -	bool nearby_tab_active	= (cur_tab == NEARBY_TAB_NAME);  	bool friends_tab_active = (cur_tab == FRIENDS_TAB_NAME);  	bool group_tab_active	= (cur_tab == GROUP_TAB_NAME);  	//bool recent_tab_active	= (cur_tab == RECENT_TAB_NAME); @@ -856,28 +789,15 @@ void LLPanelPeople::updateButtons()  	bool item_selected = (selected_uuids.size() == 1);  	bool multiple_selected = (selected_uuids.size() >= 1); -	buttonSetVisible("group_info_btn",		group_tab_active); -	buttonSetVisible("chat_btn",			group_tab_active); -	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); -  	if (group_tab_active)  	{ -		bool cur_group_active = true; -  		if (item_selected)  		{  			selected_id = mGroupList->getSelectedUUID(); -			cur_group_active = (gAgent.getGroupID() == selected_id);  		}  		LLPanel* groups_panel = mTabContainer->getCurrentPanel(); -		groups_panel->getChildView("activate_btn")->setEnabled(item_selected && !cur_group_active); // "none" or a non-active group selected -		groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); +		groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected  	}  	else  	{ @@ -893,26 +813,20 @@ void LLPanelPeople::updateButtons()  		LLPanel* cur_panel = mTabContainer->getCurrentPanel();  		if (cur_panel)  		{ -			cur_panel->getChildView("add_friend_btn")->setEnabled(!is_friend); +			if (cur_panel->hasChild("add_friend_btn", TRUE)) +				cur_panel->getChildView("add_friend_btn")->setEnabled(item_selected && !is_friend); +  			if (friends_tab_active)  			{ -				cur_panel->getChildView("del_btn")->setEnabled(multiple_selected); +				cur_panel->getChildView("friends_del_btn")->setEnabled(multiple_selected); +			} + +			if (!group_tab_active) +			{ +				cur_panel->getChildView("gear_btn")->setEnabled(multiple_selected);  			}  		}  	} - -	bool enable_calls = LLVoiceClient::getInstance()->isVoiceWorking() && LLVoiceClient::getInstance()->voiceEnabled(); - -	buttonSetEnabled("view_profile_btn",item_selected); -	buttonSetEnabled("share_btn",		item_selected); -	buttonSetEnabled("im_btn",			multiple_selected); // allow starting the friends conference for multiple selection -	buttonSetEnabled("call_btn",		multiple_selected && enable_calls); -	buttonSetEnabled("teleport_btn",	multiple_selected && LLAvatarActions::canOfferTeleport(selected_uuids)); - -	bool none_group_selected = item_selected && selected_id.isNull(); -	buttonSetEnabled("group_info_btn", !none_group_selected); -	buttonSetEnabled("group_call_btn", !none_group_selected && enable_calls); -	buttonSetEnabled("chat_btn", !none_group_selected);  }  std::string LLPanelPeople::getActiveTabName() const @@ -943,6 +857,9 @@ LLUUID LLPanelPeople::getCurrentItemID() const  	if (cur_tab == GROUP_TAB_NAME)  		return mGroupList->getSelectedUUID(); +	if (cur_tab == BLOCKED_TAB_NAME) +		return LLUUID::null; // FIXME? +  	llassert(0 && "unknown tab selected");  	return LLUUID::null;  } @@ -963,6 +880,8 @@ void LLPanelPeople::getCurrentItemIDs(uuid_vec_t& selected_uuids) const  		mRecentList->getSelectedUUIDs(selected_uuids);  	else if (cur_tab == GROUP_TAB_NAME)  		mGroupList->getSelectedUUIDs(selected_uuids); +	else if (cur_tab == BLOCKED_TAB_NAME) +		selected_uuids.clear(); // FIXME?  	else  		llassert(0 && "unknown tab selected"); @@ -1031,49 +950,60 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save  	}  } -bool LLPanelPeople::isRealGroup() -{ -	return getCurrentItemID() != LLUUID::null; -} -  void LLPanelPeople::onFilterEdit(const std::string& search_string)  { -	mFilterSubStringOrig = search_string; -	LLStringUtil::trimHead(mFilterSubStringOrig); +	const S32 cur_tab_idx = mTabContainer->getCurrentPanelIndex(); +	std::string& filter = mSavedOriginalFilters[cur_tab_idx]; +	std::string& saved_filter = mSavedFilters[cur_tab_idx]; + +	filter = search_string; +	LLStringUtil::trimHead(filter); +  	// Searches are case-insensitive -	std::string search_upper = mFilterSubStringOrig; +	std::string search_upper = filter;  	LLStringUtil::toUpper(search_upper); -	if (mFilterSubString == search_upper) +	if (saved_filter == search_upper)  		return; -	mFilterSubString = search_upper; +	saved_filter = search_upper; -	//store accordion tabs state before any manipulation with accordion tabs -	if(!mFilterSubString.empty()) +	// Apply new filter to the current tab. +	const std::string cur_tab = getActiveTabName(); +	if (cur_tab == NEARBY_TAB_NAME) +	{ +		mNearbyList->setNameFilter(filter); +	} +	else if (cur_tab == FRIENDS_TAB_NAME) +	{ +		// store accordion tabs opened/closed state before any manipulation with accordion tabs +		if (!saved_filter.empty())  	{  		notifyChildren(LLSD().with("action","store_state"));  	} - -	// Apply new filter. -	mNearbyList->setNameFilter(mFilterSubStringOrig); -	mOnlineFriendList->setNameFilter(mFilterSubStringOrig); -	mAllFriendList->setNameFilter(mFilterSubStringOrig); -	mRecentList->setNameFilter(mFilterSubStringOrig); -	mGroupList->setNameFilter(mFilterSubStringOrig); +		mOnlineFriendList->setNameFilter(filter); +		mAllFriendList->setNameFilter(filter);  	setAccordionCollapsedByUser("tab_online", false);  	setAccordionCollapsedByUser("tab_all", false); -  	showFriendsAccordionsIfNeeded(); -	//restore accordion tabs state _after_ all manipulations... -	if(mFilterSubString.empty()) +		// restore accordion tabs state _after_ all manipulations +		if(saved_filter.empty())  	{  		notifyChildren(LLSD().with("action","restore_state"));  	}  } +	else if (cur_tab == GROUP_TAB_NAME) +	{ +		mGroupList->setNameFilter(filter); +	} +	else if (cur_tab == RECENT_TAB_NAME) +	{ +		mRecentList->setNameFilter(filter); +	} +}  void LLPanelPeople::onTabSelected(const LLSD& param)  { @@ -1081,11 +1011,6 @@ void LLPanelPeople::onTabSelected(const LLSD& param)  	updateButtons();  	showFriendsAccordionsIfNeeded(); - -	if (GROUP_TAB_NAME == tab_name) -		mFilterEditor->setLabel(getString("groups_filter_label")); -	else -		mFilterEditor->setLabel(getString("people_filter_label"));  }  void LLPanelPeople::onAvatarListDoubleClicked(LLUICtrl* ctrl) @@ -1127,12 +1052,6 @@ void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list)  	updateButtons();  } -void LLPanelPeople::onViewProfileButtonClicked() -{ -	LLUUID id = getCurrentItemID(); -	LLAvatarActions::showProfile(id); -} -  void LLPanelPeople::onAddFriendButtonClicked()  {  	LLUUID id = getCurrentItemID(); @@ -1191,11 +1110,6 @@ void LLPanelPeople::onDeleteFriendButtonClicked()  	}  } -void LLPanelPeople::onGroupInfoButtonClicked() -{ -	LLGroupActions::show(getCurrentItemID()); -} -  void LLPanelPeople::onChatButtonClicked()  {  	LLUUID group_id = getCurrentItemID(); @@ -1203,6 +1117,14 @@ void LLPanelPeople::onChatButtonClicked()  		LLGroupActions::startIM(group_id);  } +void LLPanelPeople::onGearButtonClicked(LLUICtrl* btn) +{ +	uuid_vec_t selected_uuids; +	getCurrentItemIDs(selected_uuids); +	// Spawn at bottom left corner of the button. +	LLPanelPeopleMenus::gNearbyMenu.show(btn, selected_uuids, 0, 0); +} +  void LLPanelPeople::onImButtonClicked()  {  	uuid_vec_t selected_uuids; @@ -1219,11 +1141,6 @@ void LLPanelPeople::onImButtonClicked()  	}  } -void LLPanelPeople::onActivateButtonClicked() -{ -	LLGroupActions::activate(mGroupList->getSelectedUUID()); -} -  // static  void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)  { @@ -1231,19 +1148,15 @@ void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAv  		LLAvatarActions::requestFriendshipDialog(ids[0], names[0].getCompleteName());  } -void LLPanelPeople::onGroupPlusButtonClicked() +bool LLPanelPeople::onGroupPlusButtonValidate()  {  	if (!gAgent.canJoinGroups())  	{  		LLNotificationsUtil::add("JoinedTooManyGroups"); -		return; +		return false;  	} -	LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get(); -	if (!plus_menu) -		return; - -	showGroupMenu(plus_menu); +	return true;  }  void LLPanelPeople::onGroupMinusButtonClicked() @@ -1288,10 +1201,6 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)  		mAllFriendList->showPermissions(show_permissions);  		mOnlineFriendList->showPermissions(show_permissions);  	} -	else if (chosen_item == "panel_block_list_sidetray") -	{ -		LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); -	}  }  void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata) @@ -1324,10 +1233,6 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)  	{  		setSortOrder(mNearbyList, E_SORT_BY_DISTANCE);  	} -	else if (chosen_item == "panel_block_list_sidetray") -	{ -		LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); -	}  }  bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata) @@ -1361,10 +1266,6 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)  	{  		mRecentList->toggleIcons();  	} -	else if (chosen_item == "panel_block_list_sidetray") -	{ -		LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); -	}  }  bool LLPanelPeople::onFriendsViewSortMenuItemCheck(const LLSD& userdata)  @@ -1393,40 +1294,6 @@ bool LLPanelPeople::onRecentViewSortMenuItemCheck(const LLSD& userdata)  	return false;  } -void LLPanelPeople::onCallButtonClicked() -{ -	uuid_vec_t selected_uuids; -	getCurrentItemIDs(selected_uuids); - -	if (selected_uuids.size() == 1) -	{ -		// initiate a P2P voice chat with the selected user -		LLAvatarActions::startCall(getCurrentItemID()); -	} -	else if (selected_uuids.size() > 1) -	{ -		// initiate an ad-hoc voice chat with multiple users -		LLAvatarActions::startAdhocCall(selected_uuids); -	} -} - -void LLPanelPeople::onGroupCallButtonClicked() -{ -	LLGroupActions::startCall(getCurrentItemID()); -} - -void LLPanelPeople::onTeleportButtonClicked() -{ -	uuid_vec_t selected_uuids; -	getCurrentItemIDs(selected_uuids); -	LLAvatarActions::offerTeleport(selected_uuids); -} - -void LLPanelPeople::onShareButtonClicked() -{ -	LLAvatarActions::share(getCurrentItemID()); -} -  void LLPanelPeople::onMoreButtonClicked()  {  	// *TODO: not implemented yet diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 46c58cd139..da27f83074 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -80,31 +80,22 @@ private:  	std::string				getActiveTabName() const;  	LLUUID					getCurrentItemID() const;  	void					getCurrentItemIDs(uuid_vec_t& selected_uuids) const; -	void					buttonSetVisible(std::string btn_name, BOOL visible); -	void					buttonSetEnabled(const std::string& btn_name, bool enabled); -	void					buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb);  	void					showGroupMenu(LLMenuGL* menu);  	void					setSortOrder(LLAvatarList* list, ESortOrder order, bool save = true);  	// UI callbacks  	void					onFilterEdit(const std::string& search_string);  	void					onTabSelected(const LLSD& param); -	void					onViewProfileButtonClicked();  	void					onAddFriendButtonClicked();  	void					onAddFriendWizButtonClicked();  	void					onDeleteFriendButtonClicked(); -	void					onGroupInfoButtonClicked();  	void					onChatButtonClicked(); +	void					onGearButtonClicked(LLUICtrl* btn);  	void					onImButtonClicked(); -	void					onCallButtonClicked(); -	void					onGroupCallButtonClicked(); -	void					onTeleportButtonClicked(); -	void					onShareButtonClicked();  	void					onMoreButtonClicked(); -	void					onActivateButtonClicked();  	void					onAvatarListDoubleClicked(LLUICtrl* ctrl);  	void					onAvatarListCommitted(LLAvatarList* list); -	void					onGroupPlusButtonClicked(); +	bool					onGroupPlusButtonValidate();  	void					onGroupMinusButtonClicked();  	void					onGroupPlusMenuItemClicked(const LLSD& userdata); @@ -113,8 +104,6 @@ private:  	void					onGroupsViewSortMenuItemClicked(const LLSD& userdata);  	void					onRecentViewSortMenuItemClicked(const LLSD& userdata); -	//returns false only if group is "none" -	bool					isRealGroup();  	bool					onFriendsViewSortMenuItemCheck(const LLSD& userdata);  	bool					onRecentViewSortMenuItemCheck(const LLSD& userdata);  	bool					onNearbyViewSortMenuItemCheck(const LLSD& userdata); @@ -135,7 +124,6 @@ private:  	bool					isAccordionCollapsedByUser(LLUICtrl* acc_tab);  	bool					isAccordionCollapsedByUser(const std::string& name); -	LLFilterEditor*			mFilterEditor;  	LLTabContainer*			mTabContainer;  	LLAvatarList*			mOnlineFriendList;  	LLAvatarList*			mAllFriendList; @@ -144,24 +132,13 @@ private:  	LLGroupList*			mGroupList;  	LLNetMap*				mMiniMap; -	LLHandle<LLView>		mGroupPlusMenuHandle; -	LLHandle<LLView>		mNearbyViewSortMenuHandle; -	LLHandle<LLView>		mFriendsViewSortMenuHandle; -	LLHandle<LLView>		mGroupsViewSortMenuHandle; -	LLHandle<LLView>		mRecentViewSortMenuHandle; +	std::vector<std::string> mSavedOriginalFilters; +	std::vector<std::string> mSavedFilters;  	Updater*				mFriendListUpdater;  	Updater*				mNearbyListUpdater;  	Updater*				mRecentListUpdater;  	Updater*				mButtonsUpdater; - -	LLMenuButton*			mNearbyGearButton; -	LLMenuButton*			mFriendsGearButton; -	LLMenuButton*			mGroupsGearButton; -	LLMenuButton*			mRecentGearButton; - -	std::string				mFilterSubString; -	std::string				mFilterSubStringOrig;  };  #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index f12c4de2f7..c9eebe24d3 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -51,6 +51,7 @@ LLContextMenu* NearbyMenu::createMenu()  	// set up the callbacks for all of the avatar menu items  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;  	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +	LLContextMenu* menu;  	if ( mUUIDs.size() == 1 )  	{ @@ -67,20 +68,21 @@ LLContextMenu* NearbyMenu::createMenu()  		registrar.add("Avatar.Share",			boost::bind(&LLAvatarActions::share,					id));  		registrar.add("Avatar.Pay",				boost::bind(&LLAvatarActions::pay,						id));  		registrar.add("Avatar.BlockUnblock",	boost::bind(&LLAvatarActions::toggleBlock,				id)); +		registrar.add("Avatar.InviteToGroup",	boost::bind(&LLAvatarActions::inviteToGroup,			id));  		enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem,	this, _2));  		enable_registrar.add("Avatar.CheckItem",  boost::bind(&NearbyMenu::checkContextMenuItem,	this, _2));  		// create the context menu from the XUI -		return createFromFile("menu_people_nearby.xml"); +		menu = createFromFile("menu_people_nearby.xml");  	}  	else  	{  		// Set up for multi-selected People  		// registrar.add("Avatar.AddFriend",	boost::bind(&LLAvatarActions::requestFriendshipDialog,	mUUIDs)); // *TODO: unimplemented -		registrar.add("Avatar.IM",			boost::bind(&LLAvatarActions::startConference,			mUUIDs)); -		registrar.add("Avatar.Call",		boost::bind(&LLAvatarActions::startAdhocCall,			mUUIDs)); +		registrar.add("Avatar.IM",			boost::bind(&LLAvatarActions::startConference,			mUUIDs, LLUUID::null)); +		registrar.add("Avatar.Call",		boost::bind(&LLAvatarActions::startAdhocCall,			mUUIDs, LLUUID::null));  		registrar.add("Avatar.OfferTeleport",	boost::bind(&NearbyMenu::offerTeleport,					this));  		registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog,		mUUIDs));  		// registrar.add("Avatar.Share",		boost::bind(&LLAvatarActions::startIM,					mUUIDs)); // *TODO: unimplemented @@ -88,8 +90,10 @@ LLContextMenu* NearbyMenu::createMenu()  		enable_registrar.add("Avatar.EnableItem",	boost::bind(&NearbyMenu::enableContextMenuItem,	this, _2));  		// create the context menu from the XUI -		return createFromFile("menu_people_nearby_multiselect.xml"); +		menu = createFromFile("menu_people_nearby_multiselect.xml");  	} + +    return menu;  }  bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp index 280cc11179..854deb00d0 100644 --- a/indra/newview/llpaneltopinfobar.cpp +++ b/indra/newview/llpaneltopinfobar.cpp @@ -230,7 +230,7 @@ void LLPanelTopInfoBar::buildLocationString(std::string& loc_str, bool show_coor  void LLPanelTopInfoBar::setParcelInfoText(const std::string& new_text)  {  	LLRect old_rect = getRect(); -	const LLFontGL* font = mParcelInfoText->getDefaultFont(); +	const LLFontGL* font = mParcelInfoText->getFont();  	S32 new_text_width = font->getWidth(new_text);  	mParcelInfoText->setText(new_text); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 975a6c67d8..47518a365f 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -32,6 +32,7 @@  #include "llagent.h"  #include "llimview.h" +#include "llpanelpeoplemenus.h"  #include "llnotificationsutil.h"  #include "llparticipantlist.h"  #include "llspeakers.h" @@ -197,10 +198,10 @@ private:  	uuid_set_t mAvalineCallers;  }; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,  +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,  									 LLAvatarList* avatar_list,  									 bool use_context_menu/* = true*/, -									 bool exclude_agent /*= true*/,  +									 bool exclude_agent /*= true*/,  									 bool can_toggle_icons /*= true*/) :  	mSpeakerMgr(data_source),  	mAvatarList(avatar_list), @@ -233,8 +234,9 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,  	if (use_context_menu)  	{ -		mParticipantListMenu = new LLParticipantListMenu(*this); -		mAvatarList->setContextMenu(mParticipantListMenu); +		//mParticipantListMenu = new LLParticipantListMenu(*this); +		//mAvatarList->setContextMenu(mParticipantListMenu); +		mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);  	}  	else  	{ @@ -473,6 +475,7 @@ void LLParticipantList::update()  {  	mSpeakerMgr->update(true); +	// Need to resort the participant list if it's in sort by recent speaker order.  	if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered())  	{  		// Resort avatar list @@ -670,7 +673,7 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::  	return mParent.onSpeakerMuteEvent(event, userdata);  } -LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() +/*LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  {  	// set up the callbacks for all of the avatar menu items  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -708,7 +711,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  	main_menu->arrangeAndClear();  	return main_menu; -} +}*/  void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y)  { diff --git a/indra/newview/llplacesfolderview.cpp b/indra/newview/llplacesfolderview.cpp new file mode 100644 index 0000000000..3caa93ae71 --- /dev/null +++ b/indra/newview/llplacesfolderview.cpp @@ -0,0 +1,74 @@ +/**  +* @file llplacesfolderview.cpp +* @brief llplacesfolderview used within llplacesinventorypanel +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llplacesfolderview.h" + +#include "llplacesinventorypanel.h" +#include "llpanellandmarks.h" + +LLPlacesFolderView::LLPlacesFolderView(const LLFolderView::Params& p) +    : LLFolderView(p) +{ +    // we do not need auto select functionality in places landmarks, so override default behavior. +    // this disables applying of the LLSelectFirstFilteredItem in LLFolderView::doIdle. +    // Fixed issues: EXT-1631, EXT-4994. +    mAutoSelectOverride = TRUE; +} + +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 = static_cast<LLFolderViewModelItemInventory*>(getCurSelectedItem()->getViewModelItem())->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; +} + diff --git a/indra/newview/llplacesfolderview.h b/indra/newview/llplacesfolderview.h new file mode 100644 index 0000000000..8c5be39b5e --- /dev/null +++ b/indra/newview/llplacesfolderview.h @@ -0,0 +1,72 @@ +/**  +* @file   llplacesfolderview.h +* @brief  llplacesfolderview used within llplacesinventorypanel +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLPLACESFOLDERVIEW_H +#define LL_LLPLACESFOLDERVIEW_H + +#include "llfolderview.h" +#include "llinventorypanel.h" + +class LLLandmarksPanel; + +class LLPlacesFolderView : public LLFolderView +{ +public: + +    struct Params : public LLInitParam::Block<Params, LLFolderView::Params> +    { +        Params() +		{} +    }; + +	LLPlacesFolderView(const LLFolderView::Params& 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; +	} + +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_LLPLACESFOLDERVIEW_H + diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index fe4cc0f55f..ebd9604c5b 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -85,34 +85,33 @@ void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  { +	std::vector<std::string> items; +	std::vector<std::string> disabled_items; + +	LLInventoryPanel* inv_panel = mInventoryPanel.get(); +	bool is_open = false; +	if (inv_panel)  	{ -		std::vector<std::string> items; -		std::vector<std::string> disabled_items; +		LLFolderViewFolder* folder =  dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID)); +		is_open = (NULL != folder) && folder->isOpen(); +	} -		LLInventoryPanel* inv_panel = mInventoryPanel.get(); -		bool is_open = false; -		if (inv_panel) -		{ -			LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); -			is_open = (NULL != folder) && folder->isOpen(); -		} +	// collect all items' names +	fill_items_with_menu_items(items, menu); -		// collect all items' names -		fill_items_with_menu_items(items, menu); +	// remove expand or collapse menu item depend on folder state +	std::string collapse_expand_item_to_hide(is_open ? "expand" :  "collapse"); +	std::vector<std::string>::iterator it = std::find(items.begin(),  items.end(), collapse_expand_item_to_hide); +	if (it != items.end())	items.erase(it); -		// remove expand or collapse menu item depend on folder state -		std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse"); -		std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide); -		if (it != items.end())	items.erase(it); -		// Disabled items are processed via LLLandmarksPanel::isActionEnabled() -		// they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601  +	// Disabled items are processed via LLLandmarksPanel::isActionEnabled() +	// they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601  -		// repeat parent functionality - 		sSelf = getHandle(); // necessary for "New Folder" functionality +	// repeat parent functionality + 	sSelf = getHandle(); // necessary for "New Folder" functionality -		hide_context_entries(menu, items, disabled_items); -	} +	hide_context_entries(menu, items, disabled_items);  }  //virtual @@ -140,7 +139,7 @@ LLFolderViewFolder* LLPlacesFolderBridge::getFolder()  	LLInventoryPanel* inv_panel = mInventoryPanel.get();  	if (inv_panel)  	{ -		folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); +		folder =    dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID));  	}  	return folder; @@ -152,6 +151,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  	LLAssetType::EType actual_asset_type,  	LLInventoryType::EType inv_type,  	LLInventoryPanel* inventory, +	LLFolderViewModelInventory* view_model,  	LLFolderView* root,  	const LLUUID& uuid,  	U32 flags/* = 0x00*/) const @@ -170,11 +170,12 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  		if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)  		{  			// *TODO: Create a link folder handler instead if it is necessary -			new_listener = LLInventoryFVBridgeBuilder::createBridge( +			new_listener = LLInventoryFolderViewModelBuilder::createBridge(  				asset_type,  				actual_asset_type,  				inv_type,  				inventory, +				view_model,  				root,  				uuid,  				flags); @@ -183,11 +184,12 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  		new_listener = new LLPlacesFolderBridge(inv_type, inventory, root, uuid);  		break;  	default: -		new_listener = LLInventoryFVBridgeBuilder::createBridge( +		new_listener = LLInventoryFolderViewModelBuilder::createBridge(  			asset_type,  			actual_asset_type,  			inv_type,  			inventory, +			view_model,  			root,  			uuid,  			flags); diff --git a/indra/newview/llplacesinventorybridge.h b/indra/newview/llplacesinventorybridge.h index 52beacef9c..07d18d03c5 100644 --- a/indra/newview/llplacesinventorybridge.h +++ b/indra/newview/llplacesinventorybridge.h @@ -82,13 +82,14 @@ protected:   *   * It builds Bridges for Landmarks and Folders in Places Landmarks Panel   */ -class LLPlacesInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder +class LLPlacesInventoryBridgeBuilder : public LLInventoryFolderViewModelBuilder  {  public:  	/*virtual*/ LLInvFVBridge* createBridge(LLAssetType::EType asset_type,  											LLAssetType::EType actual_asset_type,  											LLInventoryType::EType inv_type,  											LLInventoryPanel* inventory, +											LLFolderViewModelInventory* view_model,  											LLFolderView* root,  											const LLUUID& uuid,  											U32 flags = 0x00) const; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index f7823f4fe8..01586a4d91 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -30,7 +30,8 @@  #include "llplacesinventorypanel.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" +#include "llplacesfolderview.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llpanellandmarks.h" @@ -57,44 +58,34 @@ LLPlacesInventoryPanel::~LLPlacesInventoryPanel()  	delete mSavedFolderState;  } -void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ -	// Determine the root folder in case specified, and -	// build the views starting with that folder. -	const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(params.start_folder); - -	LLUUID root_id; -	if ("LIBRARY" == params.start_folder()) -	{ -		root_id = gInventory.getLibraryRootFolderID(); -	} -	else -	{ -		root_id = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null); -	} - -	LLRect folder_rect(0, -		0, -		getRect().getWidth(), -		0); -	LLPlacesFolderView::Params p; -	p.name = getName(); -	p.title = getLabel(); -	p.rect = folder_rect; -	p.listener =  mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, -													LLAssetType::AT_CATEGORY, -													LLInventoryType::IT_CATEGORY, -													this, -													NULL, -													root_id); -	p.parent_panel = this; -	p.allow_multiselect = mAllowMultiSelect; -	p.use_ellipses = true;	// truncate inventory item text so remove horizontal scroller -	mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p); +LLFolderView * LLPlacesInventoryPanel::createFolderRoot(LLUUID root_id ) +{ +    LLPlacesFolderView::Params p; +     +    p.name = getName(); +    p.title = getLabel(); +    p.rect = LLRect(0, 0, getRect().getWidth(), 0); +    p.parent_panel = this; +    p.tool_tip = p.name; +    p.listener = mInvFVBridgeBuilder->createBridge(	LLAssetType::AT_CATEGORY, +        LLAssetType::AT_CATEGORY, +        LLInventoryType::IT_CATEGORY, +        this, +        &mInventoryViewModel, +        NULL, +        root_id); +    p.view_model = &mInventoryViewModel; +    p.use_label_suffix = mParams.use_label_suffix; +    p.allow_multiselect = mAllowMultiSelect; +    p.show_empty_message = mShowEmptyMessage; +    p.show_item_link_overlays = mShowItemLinkOverlays; +    p.root = NULL; +    p.use_ellipses = mParams.folder_view.use_ellipses; + +    return LLUICtrlFactory::create<LLPlacesFolderView>(p);  } -  // save current folder open state  void LLPlacesInventoryPanel::saveFolderState()  { @@ -128,59 +119,3 @@ S32	LLPlacesInventoryPanel::notify(const LLSD& info)  	}  	return 0;  } - -/************************************************************************/ -/* PROTECTED METHODS                                                    */ -/************************************************************************/ - - - -/************************************************************************/ -/*              LLPlacesFolderView implementation                       */ -/************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -//  PUBLIC METHODS -////////////////////////////////////////////////////////////////////////// - -LLPlacesFolderView::LLPlacesFolderView(const LLFolderView::Params& p) -: LLFolderView(p) -{ -	// we do not need auto select functionality in places landmarks, so override default behavior. -	// this disables applying of the LLSelectFirstFilteredItem in LLFolderView::doIdle. -	// Fixed issues: EXT-1631, EXT-4994. -	mAutoSelectOverride = TRUE; -} - -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 index f647e7f970..2805fc4257 100644 --- a/indra/newview/llplacesinventorypanel.h +++ b/indra/newview/llplacesinventorypanel.h @@ -29,9 +29,9 @@  #include "llfloaterinventory.h"  #include "llinventorypanel.h" -#include "llfolderview.h"  class LLLandmarksPanel; +class LLFolderView;  class LLPlacesInventoryPanel : public LLInventoryPanel  { @@ -46,8 +46,7 @@ public:  	LLPlacesInventoryPanel(const Params& p);  	~LLPlacesInventoryPanel(); -	/*virtual*/ void buildFolderView(const LLInventoryPanel::Params& params); - +    LLFolderView * createFolderRoot(LLUUID root_id );  	void saveFolderState();  	void restoreFolderState(); @@ -57,36 +56,4 @@ private:  	LLSaveFolderState*			mSavedFolderState;  }; - -class LLPlacesFolderView : public LLFolderView -{ -public: -	LLPlacesFolderView(const LLFolderView::Params& 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/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 88727bf59b..29eb5ce69e 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -305,7 +305,11 @@ BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask)  {  	if (mEditorCore)  	{ -		return mEditorCore->handleKeyHere(key, mask); +		BOOL handled = mEditorCore->handleKeyHere(key, mask); +		if (!handled) +		{ +			LLFloater::handleKeyHere(key, mask); +		}  	}  	return FALSE; diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index d340b304ca..a4a0198305 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -253,12 +253,26 @@ void LLScreenChannel::addToast(const LLToast::Params& p)  {  	bool store_toast = false, show_toast = false; -	mDisplayToastsAlways ? show_toast = true : show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); +	if (mDisplayToastsAlways) +	{ +		show_toast = true; +	} +	else +	{ +		show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); +	}  	store_toast = !show_toast && p.can_be_stored && mCanStoreToasts;  	if(!show_toast && !store_toast)  	{ -		mRejectToastSignal(p.notif_id); +		LLNotificationPtr notification = LLNotifications::instance().find(p.notif_id); + +		if (notification && +			(!notification->canLogToIM() || !notification->hasFormElements())) +		{ +			// only cancel notification if it isn't being used in IM session +			LLNotifications::instance().cancel(notification); +		}  		return;  	} @@ -371,7 +385,7 @@ void LLScreenChannel::storeToast(ToastElem& toast_elem)  	const LLToast* toast = toast_elem.getToast();  	if (toast)  	{ -		mStoredToastList.push_back(toast_elem); +	mStoredToastList.push_back(toast_elem);  		mOnStoreToast(toast->getPanel(), toast->getNotificationID());  	}  } @@ -410,14 +424,14 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)  	LLToast* toast = it->getToast();  	if (toast)  	{ -		if(toast->getVisible()) -		{ -			// toast is already in channel -			return; -		} +	if(toast->getVisible()) +	{ +		// toast is already in channel +		return; +	} -		toast->setIsHidden(false); -		toast->startTimer(); +	toast->setIsHidden(false); +	toast->startTimer();  		mToastList.push_back(*it);  	} @@ -425,34 +439,12 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)  }  //-------------------------------------------------------------------------- -void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) -{ -	// *TODO: may be remove this function -	std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - -	if( it == mStoredToastList.end() ) -		return; - -	const LLToast* toast = it->getToast(); -	if (toast) -	{ -		mRejectToastSignal(toast->getNotificationID()); -	} - -	// Call find() once more, because the mStoredToastList could have been changed -	// in mRejectToastSignal callback and the iterator could have become invalid. -	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); -	if (it != mStoredToastList.end()) -	{ -		mStoredToastList.erase(it); -	} -} - -//--------------------------------------------------------------------------  void LLScreenChannel::killToastByNotificationID(LLUUID id)  {  	// searching among toasts on a screen  	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); +	LLNotificationPtr notification = LLNotifications::instance().find(id); +	if (!notification) return;  	if( it != mToastList.end())  	{ @@ -465,42 +457,67 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)  		//			the toast will be destroyed.  		if(toast && toast->isNotificationValid())  		{ -			mRejectToastSignal(toast->getNotificationID()); +			if (!notification->canLogToIM() || !notification->hasFormElements()) +			{ +				// only cancel notification if it isn't being used in IM session +				LLNotifications::instance().cancel(notification); +			}  		}  		else  		{ - -			deleteToast(toast); -			mToastList.erase(it); -			redrawToasts(); +			removeToastByNotificationID(id);  		} -		return;  	} - -	// searching among stored toasts -	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - -	if (it != mStoredToastList.end()) +	else  	{ -		LLToast* toast = it->getToast(); -		if (toast) +		// searching among stored toasts +		it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + +		if( it != mStoredToastList.end() )  		{ -			// send signal to a listener to let him perform some action on toast rejecting -			mRejectToastSignal(toast->getNotificationID()); -			deleteToast(toast); +			LLToast* toast = it->getToast(); +			if (toast) +			{ +				if (!notification->canLogToIM() || !notification->hasFormElements()) +				{ +					// only cancel notification if it isn't being used in IM session +					LLNotifications::instance().cancel(notification); +				} +				deleteToast(toast); +			} +		} +	 +		// Call find() once more, because the mStoredToastList could have been changed +		// via notification cancellation and the iterator could have become invalid. +		it = find(mStoredToastList.begin(), mStoredToastList.end(), id); +		if (it != mStoredToastList.end()) +		{ +			mStoredToastList.erase(it);  		}  	} +} + +void LLScreenChannel::removeToastByNotificationID(LLUUID id) +{ +	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); +	while( it != mToastList.end()) +	{ +		deleteToast(it->getToast()); +		mToastList.erase(it); +		redrawToasts(); +		// find next toast with matching id +		it = find(mToastList.begin(), mToastList.end(), id); +	} -	// Call find() once more, because the mStoredToastList could have been changed -	// in mRejectToastSignal callback and the iterator could have become invalid.  	it = find(mStoredToastList.begin(), mStoredToastList.end(), id);  	if (it != mStoredToastList.end())  	{ +		deleteToast(it->getToast());  		mStoredToastList.erase(it);  	} -  } +  void LLScreenChannel::killMatchedToasts(const Matcher& matcher)  {  	std::list<const LLToast*> to_delete = findToasts(matcher); @@ -521,11 +538,11 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)  		LLToast* toast = it->getToast();  		if (toast)  		{ -			LLPanel* old_panel = toast->getPanel(); -			toast->removeChild(old_panel); -			delete old_panel; -			toast->insertPanel(panel); -			toast->startTimer(); +		LLPanel* old_panel = toast->getPanel(); +		toast->removeChild(old_panel); +		delete old_panel; +		toast->insertPanel(panel); +		toast->startTimer();  		}  		redrawToasts();  	} @@ -679,7 +696,7 @@ void LLScreenChannel::showToastsCentre()  		return;  	} -	LLRect	toast_rect; +	LLRect	toast_rect;	  	S32		bottom = (getRect().mTop - getRect().mBottom)/2 + toast->getRect().getHeight()/2;  	std::vector<ToastElem>::reverse_iterator it; diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 56a9cf8b4b..e5f4807ab7 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -84,6 +84,7 @@ public:  	// kill or modify a toast by its ID  	virtual void		killToastByNotificationID(LLUUID id) {};  	virtual void		modifyToastNotificationByID(LLUUID id, LLSD data) {}; +	virtual void		removeToastByNotificationID(LLUUID id){};  	// hide all toasts from screen, but not remove them from a channel  	virtual void		hideToastsFromScreen() {}; @@ -175,6 +176,7 @@ public:  	void		addToast(const LLToast::Params& p);  	// kill or modify a toast by its ID  	void		killToastByNotificationID(LLUUID id); +	void		removeToastByNotificationID(LLUUID id);  	void		killMatchedToasts(const Matcher& matcher);  	void		modifyToastByNotificationID(LLUUID id, LLPanel* panel);  	// hide all toasts from screen, but not remove them from a channel @@ -195,8 +197,6 @@ public:  	void		loadStoredToastsToChannel();  	// finds a toast among stored by its Notification ID and throws it on a screen to a channel  	void		loadStoredToastByNotificationIDToChannel(LLUUID id); -	// removes a toast from stored finding it by its Notification ID  -	void		removeStoredToastByNotificationID(LLUUID id);  	// removes from channel all toasts that belongs to the certain IM session   	void		removeToastsBySessionID(LLUUID id);  	// remove all storable toasts from screen and store them @@ -227,16 +227,12 @@ public:  	// Channel's signals  	// signal on storing of faded toasts event -	typedef boost::function<void (LLPanel* info_panel, const LLUUID id)> store_tost_callback_t; -	typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_tost_signal_t; -	store_tost_signal_t mOnStoreToast;	 -	boost::signals2::connection setOnStoreToastCallback(store_tost_callback_t cb) { return mOnStoreToast.connect(cb); } -	// signal on rejecting of a toast event -	typedef boost::function<void (LLUUID id)> reject_tost_callback_t; -	typedef boost::signals2::signal<void (LLUUID id)> reject_tost_signal_t; -	reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); } +	typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_toast_signal_t; +	boost::signals2::connection addOnStoreToastCallback(store_toast_signal_t::slot_type cb) { return mOnStoreToast.connect(cb); }  private: +	store_toast_signal_t mOnStoreToast;	 +  	class ToastElem  	{  	public: diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 3b52dd552f..c3c37141ed 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -390,7 +390,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj,  	// don't include an avatar.  	LLViewerObject* root = obj; -	while(!root->isAvatar() && root->getParent() && !root->isJointChild()) +	while(!root->isAvatar() && root->getParent())  	{  		LLViewerObject* parent = (LLViewerObject*)root->getParent();  		if (parent->isAvatar()) @@ -684,7 +684,7 @@ void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_s  		// don't include an avatar.  		LLViewerObject* root = object; -		while(!root->isAvatar() && root->getParent() && !root->isJointChild()) +		while(!root->isAvatar() && root->getParent())  		{  			LLViewerObject* parent = (LLViewerObject*)root->getParent();  			if (parent->isAvatar()) @@ -1397,7 +1397,7 @@ void LLSelectMgr::promoteSelectionToRoot()  		}  		LLViewerObject* parentp = object; -		while(parentp->getParent() && !(parentp->isRootEdit() || parentp->isJointChild())) +		while(parentp->getParent() && !(parentp->isRootEdit()))  		{  			parentp = (LLViewerObject*)parentp->getParent();  		} @@ -4474,8 +4474,7 @@ struct LLSelectMgrApplyFlags : public LLSelectedObjectFunctor  	virtual bool apply(LLViewerObject* object)  	{  		if ( object->permModify() &&	// preemptive permissions check -			 object->isRoot() &&		// don't send for child objects -			 !object->isJointChild()) +			 object->isRoot()) 		// don't send for child objects  		{  			object->setFlags( mFlags, mState);  		} @@ -6330,8 +6329,6 @@ void LLSelectMgr::updateSelectionCenter()  		// matches the root prim's (affecting the orientation of the manipulators).   		bbox.addBBoxAgent( (mSelectedObjects->getFirstRootObject(TRUE))->getBoundingBoxAgent() );  -		std::vector < LLViewerObject *> jointed_objects; -  		for (LLObjectSelection::iterator iter = mSelectedObjects->begin();  			 iter != mSelectedObjects->end(); iter++)  		{ @@ -6349,11 +6346,6 @@ void LLSelectMgr::updateSelectionCenter()  			}  			bbox.addBBoxAgent( object->getBoundingBoxAgent() ); - -			if (object->isJointChild()) -			{ -				jointed_objects.push_back(object); -			}  		}  		LLVector3 bbox_center_agent = bbox.getCenterAgent(); @@ -6643,19 +6635,19 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom)  bool LLObjectSelection::is_root::operator()(LLSelectNode *node)  {  	LLViewerObject* object = node->getObject(); -	return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild()); +	return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit());  }  bool LLObjectSelection::is_valid_root::operator()(LLSelectNode *node)  {  	LLViewerObject* object = node->getObject(); -	return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild()); +	return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit());  }  bool LLObjectSelection::is_root_object::operator()(LLSelectNode *node)  {  	LLViewerObject* object = node->getObject(); -	return (object != NULL) && (object->isRootEdit() || object->isJointChild()); +	return (object != NULL) && (object->isRootEdit());  }  LLObjectSelection::LLObjectSelection() :  diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 853656905c..b143240187 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -38,7 +38,7 @@  #include "llfiltereditor.h"  #include "llfloaterreg.h"  #include "llfloaterworldmap.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "lloutfitobserver.h"  #include "llpaneleditwearable.h"  #include "llpaneloutfitsinventory.h" @@ -267,11 +267,11 @@ void LLSidepanelAppearance::onOpenOutfitButtonClicked()  		if (inventory_panel)  		{  			LLFolderView* root = inventory_panel->getRootFolder(); -			LLFolderViewItem *outfit_folder = root->getItemByID(outfit_link->getLinkedUUID()); +			LLFolderViewItem *outfit_folder =    inventory_panel->getItemByID(outfit_link->getLinkedUUID());  			if (outfit_folder)  			{  				outfit_folder->setOpen(!outfit_folder->isOpen()); -				root->setSelectionFromRoot(outfit_folder,TRUE); +				root->setSelection(outfit_folder,TRUE);  				root->scrollToShowSelection();  			}  		} diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 4f9ab318a5..acb232c77f 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -36,6 +36,7 @@  #include "llfirstuse.h"  #include "llfloatersidepanelcontainer.h"  #include "llfoldertype.h" +#include "llfolderview.h"  #include "llhttpclient.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h" @@ -259,9 +260,8 @@ void LLSidepanelInventory::updateInbox()  	//  	const bool do_not_create_folder = false; -	const bool do_not_find_in_library = false; -	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library); +	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder);  	// Set up observer to listen for creation of inbox if at least one of them doesn't exist  	if (inbox_id.isNull()) @@ -383,10 +383,10 @@ void LLSidepanelInventory::onToggleInboxBtn()  	{  		inboxPanel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight"));  		if (inboxPanel->isInVisibleChain()) -		{ -			gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); -		} +	{ +		gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());  	} +}  	else  	{  		gSavedPerAccountSettings.setS32("InventoryInboxHeight", inboxPanel->getTargetDim()); @@ -472,7 +472,7 @@ void LLSidepanelInventory::performActionOnSelection(const std::string &action)  		}  	} -	current_item->getListener()->performAction(mPanelMainInventory->getActivePanel()->getModel(), action); +	static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(mPanelMainInventory->getActivePanel()->getModel(), action);  }  void LLSidepanelInventory::onWearButtonClicked() @@ -662,7 +662,7 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem()  			return NULL;  		}  	} -	const LLUUID &item_id = current_item->getListener()->getUUID(); +	const LLUUID &item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  	LLInventoryItem *item = gInventory.getItem(item_id);  	return item;  } @@ -671,7 +671,7 @@ U32 LLSidepanelInventory::getSelectedCount()  {  	int count = 0; -	std::set<LLUUID> selection_list = mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList(); +	std::set<LLFolderViewItem*> selection_list =    mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList();  	count += selection_list.size();  	if ((count == 0) && mInboxEnabled && (mInventoryPanelInbox != NULL)) @@ -722,9 +722,9 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox)  	updateVerbs();  } -std::set<LLUUID> LLSidepanelInventory::getInboxSelectionList() +std::set<LLFolderViewItem*> LLSidepanelInventory::getInboxSelectionList()  { -	std::set<LLUUID> inventory_selected_uuids; +	std::set<LLFolderViewItem*> inventory_selected_uuids;  	if (mInboxEnabled && (mInventoryPanelInbox != NULL))  	{ diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index a33607f50d..e8b2808d4f 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -63,7 +63,7 @@ public:  	BOOL isMainInventoryPanelActive() const;  	void clearSelections(bool clearMain, bool clearInbox); -	std::set<LLUUID> getInboxSelectionList(); +    std::set<LLFolderViewItem*> getInboxSelectionList();  	void showItemInfoPanel();  	void showTaskInfoPanel(); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 78c905f6ff..e62c9c3da5 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2776,7 +2776,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)  void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color)  { -	gGL.diffuseColor4fv(color.mV); +	gGL.color4fv(color.mV);  	gGL.begin(LLRender::LINES);  	{  		gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); @@ -3498,6 +3498,8 @@ void renderPhysicsShapes(LLSpatialGroup* group)  			LLViewerObject* object = drawable->getVObj();  			if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)  			{ +				gGL.pushMatrix(); +				gGL.multMatrix((F32*) object->getRegion()->mRenderMatrix.mMatrix);  				//push face vertices for terrain  				for (S32 i = 0; i < drawable->getNumFaces(); ++i)  				{ @@ -3519,6 +3521,7 @@ void renderPhysicsShapes(LLSpatialGroup* group)  						}  					}  				} +				gGL.popMatrix();  			}  		}  	} @@ -4024,7 +4027,7 @@ void renderAgentTarget(LLVOAvatar* avatar)  	if (avatar->isSelf())  	{  		renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); -		renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); +		renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f));  		renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f));  		renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f));  	} diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index b9358cf37c..1c6f51e131 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -29,7 +29,6 @@  #include "llevent.h"  #include "lleventtimer.h" -#include "llspeakers.h"  #include "llvoicechannel.h"  class LLSpeakerMgr; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 218c35029e..ab72b4e512 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -63,7 +63,7 @@  #include "llmemorystream.h"  #include "llmessageconfig.h"  #include "llmoveview.h" -#include "llnearbychat.h" +#include "llimfloatercontainer.h"  #include "llnotifications.h"  #include "llnotificationsutil.h"  #include "llteleporthistory.h" @@ -94,6 +94,7 @@  #include "llcallingcard.h"  #include "llconsole.h"  #include "llcontainerview.h" +#include "llconversationlog.h"  #include "lldebugview.h"  #include "lldrawable.h"  #include "lleventnotifier.h" @@ -1268,6 +1269,8 @@ bool idle_startup()  		display_startup();  		LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); +		LLConversationLog::getInstance(); +  		return FALSE;  	} @@ -1378,14 +1381,9 @@ bool idle_startup()  		LLVoiceClient::getInstance()->updateSettings();  		display_startup(); -		//gCacheName is required for nearby chat history loading -		//so I just moved nearby history loading a few states further -		if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) -		{ -			LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); -			if (nearby_chat) nearby_chat->loadHistory(); -		} -		display_startup(); +		// create a container's instance for start a controlling conversation windows +		// by the voice's events +		LLIMFloaterContainer::getInstance();  		// *Note: this is where gWorldMap used to be initialized. @@ -2165,7 +2163,6 @@ bool idle_startup()  		LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); -		LLIMFloater::initIMFloater();  		display_startup();  		llassert(LLPathfindingManager::getInstance() != NULL); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 0cb6c85012..18e0d9d0d2 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -433,13 +433,19 @@ BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mas  //////////////////////////////////////////////////////////////////////////  // PUBLIC METHODS +LLNotificationWellWindow::WellNotificationChannel::WellNotificationChannel(LLNotificationWellWindow* well_window) +:	LLNotificationChannel(LLNotificationChannel::Params().name(well_window->getPathname())), +	mWellWindow(well_window) +{ +	connectToChannel("Notifications"); +	connectToChannel("Group Notifications"); +	connectToChannel("Offer"); +} +  LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) -: LLSysWellWindow(key) +:	LLSysWellWindow(key)  { -	// init connections to the list's update events -	connectListUpdaterToSignal("notify"); -	connectListUpdaterToSignal("groupnotify"); -	connectListUpdaterToSignal("offer"); +	mNotificationUpdates.reset(new WellNotificationChannel(this));  }  // static @@ -519,7 +525,7 @@ void LLNotificationWellWindow::initChannel()  	LLSysWellWindow::initChannel();  	if(mChannel)  	{ -		mChannel->setOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); +		mChannel->addOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2));  	}  } @@ -546,20 +552,6 @@ void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id)  	addItem(p);  } -void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type) -{ -	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); -	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); -	if(n_handler) -	{ -		n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1)); -	} -	else -	{ -		llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; -	} -} -  void LLNotificationWellWindow::onItemClick(LLSysWellItem* item)  {  	LLUUID id = item->getID(); @@ -574,6 +566,12 @@ void LLNotificationWellWindow::onItemClose(LLSysWellItem* item)  		mChannel->killToastByNotificationID(id);  } +void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) +{ +	removeItemByID(notify->getID()); +} + +  /************************************************************************/ @@ -867,4 +865,4 @@ bool LLIMWellWindow::confirmCloseAll(const LLSD& notification, const LLSD& respo  	return false;  } -// EOF + diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 272e9cfcb1..6be12711ac 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -34,6 +34,7 @@  #include "llscreenchannel.h"  #include "llscrollcontainer.h"  #include "llimview.h" +#include "llnotifications.h"  #include "boost/shared_ptr.hpp" @@ -48,6 +49,8 @@ class LLSysWellChiclet;  class LLSysWellWindow : public LLTransientDockableFloater  {  public: +	LOG_CLASS(LLSysWellWindow); +      LLSysWellWindow(const LLSD& key);      ~LLSysWellWindow();  	BOOL postBuild(); @@ -111,7 +114,7 @@ public:  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setVisible(BOOL visible); - +	/*virtual*/ void onAdd(LLNotificationPtr notify);  	// Operating with items  	void addItem(LLSysWellItem::Params p); @@ -119,6 +122,18 @@ public:  	void closeAll();  protected: +	struct WellNotificationChannel : public LLNotificationChannel +	{ +		WellNotificationChannel(LLNotificationWellWindow*); +		void onDelete(LLNotificationPtr notify) +		{ +			mWellWindow->removeItemByID(notify->getID()); +		}  + +		LLNotificationWellWindow* mWellWindow; +	}; + +	LLNotificationChannelPtr mNotificationUpdates;  	/*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; }  private: @@ -126,12 +141,8 @@ private:  	void initChannel();  	void clearScreenChannels(); -  	void onStoreToast(LLPanel* info_panel, LLUUID id); -	// connect counter and list updaters to the corresponding signals -	void connectListUpdaterToSignal(std::string notification_type); -  	// Handlers  	void onItemClick(LLSysWellItem* item);  	void onItemClose(LLSysWellItem* item); @@ -160,6 +171,7 @@ public:  	// LLIMSessionObserver observe triggers  	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	/*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {};  	/*virtual*/ void sessionRemoved(const LLUUID& session_id);  	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ec36cf48c2..65f0290060 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -39,7 +39,7 @@  #include "llfocusmgr.h"  #include "llviewertexture.h"  #include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "llinventory.h"  #include "llinventoryfunctions.h"  #include "llinventorymodelbackgroundfetch.h" @@ -58,6 +58,7 @@  #include "lltoolmgr.h"  #include "lltoolpipette.h"  #include "llfiltereditor.h" +#include "llwindow.h"  #include "lltool.h"  #include "llviewerwindow.h" @@ -186,7 +187,7 @@ protected:  	F32					mContextConeOpacity;  	LLSaveFolderState	mSavedFolderState;  	BOOL				mSelectedItemPinned; -	 +  	LLRadioGroup*		mModeSelector;  	LLScrollListCtrl*	mLocalScrollCtrl; @@ -372,7 +373,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)  		{  			if (!root_folder->getCurSelectedItem())  			{ -				LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID()); +				LLFolderViewItem* itemp =    mInventoryPanel->getItemByID(gInventory.getRootFolderID());  				if (itemp)  				{  					root_folder->setSelection(itemp, FALSE, FALSE); @@ -454,7 +455,7 @@ BOOL LLFloaterTexturePicker::postBuild()  		// Commented out to scroll to currently selected texture. See EXT-5403.  		// // store this filter as the default one -		// mInventoryPanel->getRootFolder()->getFilter()->markDefault(); +		// mInventoryPanel->getRootFolder()->getFilter().markDefault();  		// Commented out to stop opening all folders with textures  		// mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE); @@ -637,11 +638,10 @@ void LLFloaterTexturePicker::draw()  		LLFolderView* folder_view = mInventoryPanel->getRootFolder();  		if (!folder_view) return; -		LLInventoryFilter* filter = folder_view->getFilter(); -		if (!filter) return; +		LLFolderViewFilter& filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter(); -		bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() && -				filter->isNotDefault(); +		bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter.getCurrentGeneration() && +				filter.isNotDefault();  		// After inventory panel filter is applied we have to update  		// constraint rect for the selected item because of folder view @@ -651,8 +651,9 @@ void LLFloaterTexturePicker::draw()  		if (!is_filter_active && !mSelectedItemPinned)  		{  			folder_view->setPinningSelectedItem(mSelectedItemPinned); -			folder_view->dirtyFilter(); -			folder_view->arrangeFromRoot(); +			folder_view->getViewModelItem()->dirtyFilter(); +			//TODO RN: test..still works without this? +			//folder_view->arrangeFromRoot();  			mSelectedItemPinned = TRUE;  		} @@ -815,7 +816,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem  	if (items.size())  	{  		LLFolderViewItem* first_item = items.front(); -		LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); +		LLInventoryItem* itemp = gInventory.getItem(static_cast<LLFolderViewModelItemInventory*>(first_item->getViewModelItem())->getUUID());  		mNoCopyTextureSelected = FALSE;  		if (itemp)  		{ @@ -1011,7 +1012,7 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )  	else if (mInventoryPanel->getFilterSubString().empty())  	{  		// first letter in search term, save existing folder open state -		if (!mInventoryPanel->getRootFolder()->isFilterModified()) +		if (!mInventoryPanel->getFilter().isNotDefault())  		{  			mSavedFolderState.setApply(FALSE);  			mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); @@ -1325,7 +1326,7 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  		// (i.e. op == TEXTURE_SELECT) or texture changes via DnD.  		else if (mCommitOnSelection || op == TEXTURE_SELECT)  			mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - +			  		if(floaterp->isDirty() || id.notNull()) // mModelView->setDirty does not work.  		{  			setTentative( FALSE ); @@ -1337,10 +1338,10 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  			}  			else  			{ -				mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); -				lldebugs << "mImageItemID: " << mImageItemID << llendl; -				mImageAssetID = floaterp->getAssetID(); -				lldebugs << "mImageAssetID: " << mImageAssetID << llendl; +			mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); +			lldebugs << "mImageItemID: " << mImageItemID << llendl; +			mImageAssetID = floaterp->getAssetID(); +			lldebugs << "mImageAssetID: " << mImageAssetID << llendl;  			}  			if (op == TEXTURE_SELECT && mOnSelectCallback) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 7e6dfbc9d9..2ed7488b85 100644..100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1249,6 +1249,12 @@ bool LLTextureFetchWorker::doWork(S32 param)  				S32 max_attempts;  				if (mGetStatus == HTTP_NOT_FOUND)  				{ +					if(mWriteToCacheState == NOT_WRITE) //map tiles +					{ +						mState = DONE; +						return true; // failed, means no map tile on the empty region. +					} +  					mHTTPFailCount = max_attempts = 1; // Don't retry  					llwarns << "Texture missing from server (404): " << mUrl << llendl; diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index e1d99b1bcb..ea62f758f8 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -169,6 +169,7 @@ public:  	// get/set Toast's flags or states  	// get information whether the notification corresponding to the toast is valid or not  	bool isNotificationValid(); +  	// get toast's Notification ID  	const LLUUID getNotificationID() const { return mNotificationID;}  	// get toast's Session ID @@ -212,7 +213,7 @@ private:  	//LLRootHandle<LLToast>	mHandle; -	LLPanel* mWrapperPanel; +	LLPanel*	 mWrapperPanel;  	// timer counts a lifetime of a toast  	std::auto_ptr<LLToastLifeTimer> mTimer; @@ -220,8 +221,8 @@ private:  	F32			mToastLifetime; // in seconds  	F32			mToastFadingTime; // in seconds -	LLPanel*		mPanel; -	LLButton*		mHideBtn; +	LLPanel*	mPanel; +	LLButton*	mHideBtn;  	LLColor4	mBgColor;  	bool		mCanFade; diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 75178a6ef8..ed350ea144 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -51,7 +51,7 @@  const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT	= 7; -LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification) +LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notification)  :	LLToastPanel(notification),  	mInventoryOffer(NULL)  { @@ -112,7 +112,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification  		style.font = date_font;  	pMessageText->appendText(timeStr + "\n", TRUE, style); -	style.font = pMessageText->getDefaultFont(); +	style.font = pMessageText->getFont();  	pMessageText->appendText(message, TRUE, style);  	//attachment diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h index 7794ec9f63..dfdc6ae559 100644 --- a/indra/newview/lltoastgroupnotifypanel.h +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -47,13 +47,10 @@ class LLToastGroupNotifyPanel  public:  	void close(); -	static bool onNewNotification(const LLSD& notification); - -  	// Non-transient messages.  You can specify non-default button  	// layouts (like one for script dialogs) by passing various  	// numbers in for "layout". -	LLToastGroupNotifyPanel(LLNotificationPtr& notification); +	LLToastGroupNotifyPanel(const LLNotificationPtr& notification);  	/*virtual*/ ~LLToastGroupNotifyPanel();  protected: diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index a803387576..279dd69bc7 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -41,11 +41,11 @@ public:  	struct Params  	{  		LLNotificationPtr	notification; -		LLUUID				avatar_id; -		LLUUID				session_id; -		std::string			from; -		std::string			time; -		std::string			message; +		LLUUID				avatar_id, +							session_id; +		std::string			from, +							time, +							message;  		Params() {}  	}; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index d629f3abac..4a49922656 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -45,6 +45,9 @@  const S32 BOTTOM_PAD = VPAD * 3;  const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding  S32 BUTTON_WIDTH = 90; +// *TODO: magic numbers(???) - copied from llnotify.cpp(250) +const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  +  //static  const LLFontGL* LLToastNotifyPanel::sFont = NULL; @@ -52,172 +55,12 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;  LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; -LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : -LLToastPanel(notification), -mTextBox(NULL), -mInfoPanel(NULL), -mControlPanel(NULL), -mNumOptions(0), -mNumButtons(0), -mAddedDefaultBtn(false), -mCloseNotificationOnDestroy(true) +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images)  +:	LLToastPanel(notification), +	LLInstanceTracker<LLToastNotifyPanel, LLUUID>(notification->getID())  { -	buildFromFile( "panel_notification.xml"); -	if(rect != LLRect::null) -	{ -		this->setShape(rect); -	}		  -	mInfoPanel = getChild<LLPanel>("info_panel"); -	mControlPanel = getChild<LLPanel>("control_panel"); -	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); -	// customize panel's attributes -	// is it intended for displaying a tip? -	mIsTip = notification->getType() == "notifytip"; -	// is it a script dialog? -	mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); -	// is it a caution? -	// -	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the -	// notify xml template specifies that it is a caution -	// tip-style notification handle 'caution' differently -they display the tip in a different color -	mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; - -	// setup parameters -	// get a notification message -	mMessage = notification->getMessage(); -	// init font variables -	if (!sFont) -	{ -		sFont = LLFontGL::getFontSansSerif(); -		sFontSmall = LLFontGL::getFontSansSerifSmall(); -	} -	// initialize -	setFocusRoot(!mIsTip); -	// get a form for the notification -	LLNotificationFormPtr form(notification->getForm()); -	// get number of elements -	mNumOptions = form->getNumElements(); - -	// customize panel's outfit -	// preliminary adjust panel's layout -	//move to the end  -	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); - -	// adjust text options according to the notification type -	// add a caution textbox at the top of a caution notification -	if (mIsCaution && !mIsTip) -	{ -		mTextBox = getChild<LLTextBox>("caution_text_box"); -	} -	else -	{ -		mTextBox = getChild<LLTextEditor>("text_editor_box");  -	} - -	// *TODO: magic numbers(???) - copied from llnotify.cpp(250) -	const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  - -	mTextBox->setMaxTextLength(MAX_LENGTH); -	mTextBox->setVisible(TRUE); -	mTextBox->setPlainText(!show_images); -	mTextBox->setValue(notification->getMessage()); - -	// add buttons for a script notification -	if (mIsTip) -	{ -		adjustPanelForTipNotice(); +	init(rect, show_images);  	} -	else -	{ -		std::vector<index_button_pair_t> buttons; -		buttons.reserve(mNumOptions); -		S32 buttons_width = 0; -		// create all buttons and accumulate they total width to reshape mControlPanel -		for (S32 i = 0; i < mNumOptions; i++) -		{ -			LLSD form_element = form->getElement(i); -			if (form_element["type"].asString() != "button") -			{ -				// not a button. -				continue; -			} -			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) -			{ -				// a textbox pretending to be a button. -				continue; -			} -			LLButton* new_button = createButton(form_element, TRUE); -			buttons_width += new_button->getRect().getWidth(); -			S32 index = form_element["index"].asInteger(); -			buttons.push_back(index_button_pair_t(index,new_button)); -		} -		if (buttons.empty()) -		{ -			addDefaultButton(); -		} -		else -		{ -			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel -			S32 button_panel_height = mControlPanel->getRect().getHeight(); -			//try get an average h_pad to spread out buttons -			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); -			if(h_pad < 2*HPAD) -			{ -				/* -				 * Probably it is a scriptdialog toast -				 * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. -				 * In last case set default h_pad to avoid heaping of buttons  -				 */ -				S32 button_per_row = button_panel_width / BUTTON_WIDTH; -				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row    -				if(h_pad < 2*HPAD) // still not enough space between buttons ? -				{ -					h_pad = 2*HPAD; -				} -			} -			if (mIsScriptDialog) -			{ -				// we are using default width for script buttons so we can determinate button_rows -				//to get a number of rows we divide the required width of the buttons to button_panel_width -				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); -				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; -				//reserve one row for the ignore_btn -				button_rows++; -				//calculate required panel height for scripdialog notification. -				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; -			} -			else -			{ -				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width -				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); -				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); -				//calculate required panel height  -				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD; -			} -		 -			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed -			adjustPanelForScriptNotice(button_panel_width, button_panel_height); -			updateButtonsLayout(buttons, h_pad); -			// save buttons for later use in disableButtons() -			mButtons.assign(buttons.begin(), buttons.end()); -		} -	} -	// adjust panel's height to the text size -	mInfoPanel->setFollowsAll(); -	snapToMessageHeight(mTextBox, MAX_LENGTH); - -	if(notification->isReusable()) -	{ -		mButtonClickConnection = sButtonClickSignal.connect( -			boost::bind(&LLToastNotifyPanel::onToastPanelButtonClicked, this, _1, _2)); - -		if(notification->isRespondedTo()) -		{ -			// User selected an option in toast, now disable required buttons in IM window -			disableRespondedOptions(notification); -		} -	} -}  void LLToastNotifyPanel::addDefaultButton()  {  	LLSD form_element; @@ -235,7 +78,6 @@ void LLToastNotifyPanel::addDefaultButton()  }  LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option)  { -  	InstanceAndS32* userdata = new InstanceAndS32;  	userdata->mSelf = this;  	userdata->mButtonName = is_option ? form_element["name"].asString() : ""; @@ -245,14 +87,15 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt  	LLButton::Params p;  	bool make_small_btn = form_element["index"].asInteger() == -1 || form_element["index"].asInteger() == -2;  	const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog -	p.name(form_element["name"].asString()); -	p.label(form_element["text"].asString()); -	p.font(font); +	p.name = form_element["name"].asString(); +	p.label = form_element["text"].asString(); +	p.font = font;  	p.rect.height = BTN_HEIGHT;  	p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));  	p.rect.width = BUTTON_WIDTH;  	p.auto_resize = false;  	p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); +	p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean();  	if (mIsCaution)  	{  		p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); @@ -287,16 +130,11 @@ LLToastNotifyPanel::~LLToastNotifyPanel()  	mButtonClickConnection.disconnect();  	std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); -	if (mCloseNotificationOnDestroy && LLNotificationsUtil::find(mNotification->getID()) != NULL) -	{ -		// let reusable notification be deleted -		mNotification->setReusable(false); -		if (!mNotification->isPersistent()) +	if (mIsTip)  		{  			LLNotifications::getInstance()->cancel(mNotification);  		}  	} -}  void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 h_pad)  { @@ -393,210 +231,374 @@ void LLToastNotifyPanel::adjustPanelForTipNotice()  	}  } -typedef std::set<std::string> button_name_set_t; -typedef std::map<std::string, button_name_set_t> disable_button_map_t; +//typedef std::set<std::string> button_name_set_t; +//typedef std::map<std::string, button_name_set_t> disable_button_map_t; +// +//disable_button_map_t initUserGiveItemDisableButtonMap() +//{ +//	// see EXT-5905 for disable rules +// +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Show"); +//	disable_map.insert(std::make_pair("Show", buttons)); +// +//	buttons.insert("Discard"); +//	disable_map.insert(std::make_pair("Discard", buttons)); +// +//	buttons.insert("Mute"); +//	disable_map.insert(std::make_pair("Mute", buttons)); +// +//	return disable_map; +//} +// +//disable_button_map_t initTeleportOfferedDisableButtonMap() +//{ +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Teleport"); +//	buttons.insert("Cancel"); +// +//	disable_map.insert(std::make_pair("Teleport", buttons)); +//	disable_map.insert(std::make_pair("Cancel", buttons)); +// +//	return disable_map; +//} +// +//disable_button_map_t initFriendshipOfferedDisableButtonMap() +//{ +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Accept"); +//	buttons.insert("Decline"); +// +//	disable_map.insert(std::make_pair("Accept", buttons)); +//	disable_map.insert(std::make_pair("Decline", buttons)); +// +//	return disable_map; +//} +// +//button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) +//{ +//	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); +//	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); +//	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); +// +//	disable_button_map_t::const_iterator it; +//	disable_button_map_t::const_iterator it_end; +//	disable_button_map_t search_map; +// +//	if("UserGiveItem" == notification_name) +//	{ +//		search_map = user_give_item_disable_map; +//	} +//	else if("TeleportOffered" == notification_name) +//	{ +//		search_map = teleport_offered_disable_map; +//	} +//	else if("OfferFriendship" == notification_name) +//	{ +//		search_map = friendship_offered_disable_map; +//	} +// +//	it = search_map.find(button_name); +//	it_end = search_map.end(); +// +//	if(it_end != it) +//	{ +//		return it->second; +//	} +//	return button_name_set_t(); +//} + +//void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +//{ +	//button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); + +	//std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); +	//for ( ; it != mButtons.end(); it++) +	//{ +	//	LLButton* btn = it->second; +	//	if(buttons.find(btn->getName()) != buttons.end()) +	//	{ +	//		btn->setEnabled(FALSE); +	//	} +	//} +//} -disable_button_map_t initUserGiveItemDisableButtonMap() +// static +void LLToastNotifyPanel::onClickButton(void* data)  { -	// see EXT-5905 for disable rules - -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Show"); -	disable_map.insert(std::make_pair("Show", buttons)); +	InstanceAndS32* self_and_button = (InstanceAndS32*)data; +	LLToastNotifyPanel* self = self_and_button->mSelf; +	std::string button_name = self_and_button->mButtonName; -	buttons.insert("Discard"); -	disable_map.insert(std::make_pair("Discard", buttons)); +	LLSD response = self->mNotification->getResponseTemplate(); +	if (!self->mAddedDefaultBtn && !button_name.empty()) +	{ +		response[button_name] = true; +	} -	buttons.insert("Mute"); -	disable_map.insert(std::make_pair("Mute", buttons)); +	// disable all buttons +	self->mControlPanel->setEnabled(FALSE); -	return disable_map; +	// this might repost notification with new form data/enabled buttons +	self->mNotification->respond(response);  } -disable_button_map_t initTeleportOfferedDisableButtonMap() +void LLToastNotifyPanel::init( LLRect rect, bool show_images )  { -	disable_button_map_t disable_map; -	button_name_set_t buttons; +	deleteAllChildren(); -	buttons.insert("Teleport"); -	buttons.insert("Cancel"); +	mTextBox = NULL; +	mInfoPanel = NULL; +	mControlPanel = NULL; +	mNumOptions = 0; +	mNumButtons = 0; +	mAddedDefaultBtn = false; -	disable_map.insert(std::make_pair("Teleport", buttons)); -	disable_map.insert(std::make_pair("Cancel", buttons)); +	buildFromFile( "panel_notification.xml"); +	if(rect != LLRect::null) +	{ +		this->setShape(rect); +	}		  +	mInfoPanel = getChild<LLPanel>("info_panel"); +	mInfoPanel->setFollowsAll(); -	return disable_map; -} +	mControlPanel = getChild<LLPanel>("control_panel"); +	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); +	// customize panel's attributes +	// is it intended for displaying a tip? +	mIsTip = mNotification->getType() == "notifytip"; +	// is it a script dialog? +	mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); +	// is it a caution? +	// +	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the +	// notify xml template specifies that it is a caution +	// tip-style notification handle 'caution' differently -they display the tip in a different color +	mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; -disable_button_map_t initFriendshipOfferedDisableButtonMap() +	// setup parameters +	// get a notification message +	mMessage = mNotification->getMessage(); +	// init font variables +	if (!sFont)  { -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Accept"); -	buttons.insert("Decline"); - -	disable_map.insert(std::make_pair("Accept", buttons)); -	disable_map.insert(std::make_pair("Decline", buttons)); - -	return disable_map; +		sFont = LLFontGL::getFontSansSerif(); +		sFontSmall = LLFontGL::getFontSansSerifSmall();  } +	// initialize +	setFocusRoot(!mIsTip); +	// get a form for the notification +	LLNotificationFormPtr form(mNotification->getForm()); +	// get number of elements +	mNumOptions = form->getNumElements(); -button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) -{ -	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); -	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); -	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); - -	disable_button_map_t::const_iterator it; -	disable_button_map_t::const_iterator it_end; -	disable_button_map_t search_map; +	// customize panel's outfit +	// preliminary adjust panel's layout +	//move to the end  +	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); -	if("UserGiveItem" == notification_name) -	{ -		search_map = user_give_item_disable_map; -	} -	else if(("TeleportOffered" == notification_name) || ("TeleportOffered_MaturityExceeded" == notification_name)) +	// adjust text options according to the notification type +	// add a caution textbox at the top of a caution notification +	if (mIsCaution && !mIsTip)  	{ -		search_map = teleport_offered_disable_map; +		mTextBox = getChild<LLTextBox>("caution_text_box");  	} -	else if("OfferFriendship" == notification_name) +	else  	{ -		search_map = friendship_offered_disable_map; +		mTextBox = getChild<LLTextEditor>("text_editor_box");   	} -	it = search_map.find(button_name); -	it_end = search_map.end(); +	mTextBox->setMaxTextLength(MAX_LENGTH); +	mTextBox->setVisible(TRUE); +	mTextBox->setPlainText(!show_images); +	mTextBox->setValue(mNotification->getMessage()); -	if(it_end != it) +	// add buttons for a script notification +	if (mIsTip)  	{ -		return it->second; +		adjustPanelForTipNotice();  	} -	return button_name_set_t(); -} - -void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +	else  { -	button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); - -	std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); -	for ( ; it != mButtons.end(); it++) +		std::vector<index_button_pair_t> buttons; +		buttons.reserve(mNumOptions); +		S32 buttons_width = 0; +		// create all buttons and accumulate they total width to reshape mControlPanel +		for (S32 i = 0; i < mNumOptions; i++)  	{ -		LLButton* btn = it->second; -		if(buttons.find(btn->getName()) != buttons.end()) +			LLSD form_element = form->getElement(i); +			if (form_element["type"].asString() != "button")  		{ -			btn->setEnabled(FALSE); +				// not a button. +				continue;  		} +			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) +			{ +				// a textbox pretending to be a button. +				continue;  	} +			LLButton* new_button = createButton(form_element, TRUE); +			buttons_width += new_button->getRect().getWidth(); +			S32 index = form_element["index"].asInteger(); +			buttons.push_back(index_button_pair_t(index,new_button));  } - -// static -void LLToastNotifyPanel::onClickButton(void* data) +		if (buttons.empty())  { -	InstanceAndS32* self_and_button = (InstanceAndS32*)data; -	LLToastNotifyPanel* self = self_and_button->mSelf; -	std::string button_name = self_and_button->mButtonName; - -	LLSD response = self->mNotification->getResponseTemplate(); -	if (!self->mAddedDefaultBtn && !button_name.empty()) -	{ -		response[button_name] = true; +			addDefaultButton();  	} -	 -	bool is_reusable = self->mNotification->isReusable(); -	// When we call respond(), LLOfferInfo will delete itself in inventory_offer_callback(),  -	// lets copy it while it's still valid. -	LLOfferInfo* old_info = static_cast<LLOfferInfo*>(self->mNotification->getResponder()); -	LLOfferInfo* new_info = NULL; -	if(is_reusable && old_info) +		else  	{ -		new_info = new LLOfferInfo(*old_info); -		self->mNotification->setResponder(new_info); -	} - -	self->mNotification->respond(response); - -	if(is_reusable) +			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel +			S32 button_panel_height = mControlPanel->getRect().getHeight(); +			//try get an average h_pad to spread out buttons +			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); +			if(h_pad < 2*HPAD)  	{ -		sButtonClickSignal(self->mNotification->getID(), button_name); -	} -	else +				/* +				* Probably it is a scriptdialog toast +				* for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. +				* In last case set default h_pad to avoid heaping of buttons  +				*/ +				S32 button_per_row = button_panel_width / BUTTON_WIDTH; +				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row    +				if(h_pad < 2*HPAD) // still not enough space between buttons ?  	{ -		// disable all buttons -		self->mControlPanel->setEnabled(FALSE); +					h_pad = 2*HPAD;  	}  } - -void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +			if (mIsScriptDialog)  { -	if(mNotification->getID() == notification_id) +				// we are using default width for script buttons so we can determinate button_rows +				//to get a number of rows we divide the required width of the buttons to button_panel_width +				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); +				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; +				//reserve one row for the ignore_btn +				button_rows++; +				//calculate required panel height for scripdialog notification. +				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; +			} +			else  	{ -		disableButtons(mNotification->getName(), btn_name); -	} +				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width +				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); +				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); +				//calculate required panel height  +				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD;  } -void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) -{ -	LLSD response = notification->getResponse(); -	for (LLSD::map_const_iterator response_it = response.beginMap();  -		response_it != response.endMap(); ++response_it) -	{ -		if (response_it->second.isBoolean() && response_it->second.asBoolean()) -		{ -			// that after multiple responses there can be many pressed buttons -			// need to process them all -			disableButtons(notification->getName(), response_it->first); +			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed +			adjustPanelForScriptNotice(button_panel_width, button_panel_height); +			updateButtonsLayout(buttons, h_pad); +			// save buttons for later use in disableButtons() +			//mButtons.assign(buttons.begin(), buttons.end());  		}  	} +	// adjust panel's height to the text size +	snapToMessageHeight(mTextBox, MAX_LENGTH);  } + +//void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +//{ +//	if(mNotification->getID() == notification_id) +//	{ +//		disableButtons(mNotification->getName(), btn_name); +//	} +//} + +//void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) +//{ +//	LLSD response = notification->getResponse(); +//	for (LLSD::map_const_iterator response_it = response.beginMap();  +//		response_it != response.endMap(); ++response_it) +//	{ +//		if (response_it->second.isBoolean() && response_it->second.asBoolean()) +//		{ +//			// that after multiple responses there can be many pressed buttons +//			// need to process them all +//			disableButtons(notification->getName(), response_it->first); +//		} +//	} +//} + +  //////////////////////////////////////////////////////////////////////////  LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */, -										   bool show_images /* = true */) - : mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images) +										   bool show_images /* = true */, LLTextBase* parent_text) +:	mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images), +	mParentText(parent_text)  { -	mTextBox->setFollowsAll(); +	compactButtons();  }  LLIMToastNotifyPanel::~LLIMToastNotifyPanel()  { -	// We shouldn't delete notification when IM floater exists -	// since that notification will be reused by IM floater. -	// This may happened when IM floater reloads messages, exactly when user -	// changes layout of IM chat log(disable/enable plaintext mode). -	// See EXT-6500 -	LLIMFloater* im_floater = LLIMFloater::findInstance(mSessionID); -	if (im_floater != NULL && !im_floater->isDead()) -	{ -		mCloseNotificationOnDestroy = false; -	}  }  void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +	{ +	LLToastPanel::reshape(width, height, called_from_parent); + +	snapToMessageHeight(mTextBox, MAX_LENGTH); +	} + +void LLIMToastNotifyPanel::compactButtons()  { -	S32 text_height = mTextBox->getTextBoundingRect().getHeight(); -	S32 widget_height = mTextBox->getRect().getHeight(); -	S32 delta = text_height - widget_height; -	LLRect rc = getRect(); +	mTextBox->setFollowsAll(); -	rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height + delta); -	height = rc.getHeight(); -	width = rc.getWidth(); +	//we can't set follows in xml since it broke toasts behavior +	setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP); -	bool is_width_changed = width != getRect().getWidth(); +	const child_list_t* children = getControlPanel()->getChildList(); +	S32 offset = 0; +	// Children were added by addChild() which uses push_front to insert them into list, +	// so to get buttons in correct order reverse iterator is used (EXT-5906)  +	for (child_list_t::const_reverse_iterator it = children->rbegin(); it != children->rend(); it++) +	{ +		LLButton * button = dynamic_cast<LLButton*> (*it); +		if (button != NULL) +		{ +			button->setOrigin( offset,button->getRect().mBottom); +			button->setLeftHPad(2 * HPAD); +			button->setRightHPad(2 * HPAD); +			// set zero width before perform autoResize() +			button->setRect(LLRect(button->getRect().mLeft, +				button->getRect().mTop,  +				button->getRect().mLeft, +				button->getRect().mBottom)); +			button->setAutoResize(true); +			button->autoResize(); +			offset += HPAD + button->getRect().getWidth(); +			button->setFollowsNone(); +		} +	} -	LLToastPanel::reshape(width, height, called_from_parent); +	if (mParentText) +	{ +		mParentText->needsReflow(); +	} +} -	// Notification height required to display the text message depends on -	// the width of the text box thus if panel width is changed the text box -	// width is also changed then reshape() is called to adjust proper height. -	if (is_width_changed) +void LLIMToastNotifyPanel::updateNotification()  	{ -		reshape(width, height, called_from_parent); +	init(LLRect(), true);  	} + +void LLIMToastNotifyPanel::init( LLRect rect, bool show_images ) +{ +	LLToastNotifyPanel::init(LLRect(), show_images); + +	compactButtons();  } +  // EOF + diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index db517ec858..f93c7745af 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -47,7 +47,7 @@ class LLNotificationForm;   * @deprecated this class will be removed after all toast panel types are   *  implemented in separate classes.   */ -class LLToastNotifyPanel: public LLToastPanel  +class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID>  {  public:  	/** @@ -61,10 +61,14 @@ public:  	 * implement right class for desired toast panel. @see LLGenericTipPanel as example.  	 */  	LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); + +	virtual void init( LLRect rect, bool show_images ); +  	virtual ~LLToastNotifyPanel();  	LLPanel * getControlPanel() { return mControlPanel; } -	void setCloseNotificationOnDestroy(bool close) { mCloseNotificationOnDestroy = close; } +	virtual void updateNotification() {} +  protected:  	LLButton* createButton(const LLSD& form_element, BOOL is_option); @@ -76,8 +80,6 @@ protected:  	};  	std::vector<InstanceAndS32*> mBtnCallbackData; -	bool mCloseNotificationOnDestroy; -  	typedef std::pair<int,LLButton*> index_button_pair_t;   	void adjustPanelForScriptNotice(S32 max_width, S32 max_height);  	void adjustPanelForTipNotice(); @@ -93,9 +95,9 @@ protected:  	/**  	 * Disable specific button(s) based on notification name and clicked button  	 */ -	void disableButtons(const std::string& notification_name, const std::string& selected_button); +	//void disableButtons(const std::string& notification_name, const std::string& selected_button); -	std::vector<index_button_pair_t> mButtons; +	//std::vector<index_button_pair_t> mButtons;  	// panel elements  	LLTextBase*		mTextBox; @@ -118,7 +120,7 @@ protected:  	/**  	 * Process response data. Will disable selected options  	 */ -	void disableRespondedOptions(const LLNotificationPtr& notification); +	//void disableRespondedOptions(const LLNotificationPtr& notification);  	bool mIsTip;  	bool mAddedDefaultBtn; @@ -137,13 +139,23 @@ class LLIMToastNotifyPanel : public LLToastNotifyPanel  {  public: -	LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect = LLRect::null, bool show_images = true); +	LLIMToastNotifyPanel(LLNotificationPtr& pNotification,  +						const LLUUID& session_id,  +						const LLRect& rect = LLRect::null,  +						bool show_images = true,  +						LLTextBase* parent_text = NULL); + +	void compactButtons(); + +	virtual void updateNotification(); +	virtual void init( LLRect rect, bool show_images );  	~LLIMToastNotifyPanel();  	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);  protected: +	LLTextBase* mParentText;  	LLUUID	mSessionID;  }; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index c33fde99c5..187aee207c 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -70,7 +70,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)  	if (message->getVisible())  	{  		S32 heightDelta = 0; -		S32 maxTextHeight = message->getDefaultFont()->getLineHeight() * maxLineCount; +		S32 maxTextHeight = message->getFont()->getLineHeight() * maxLineCount;  		LLRect messageRect = message->getRect();  		S32 oldTextHeight = messageRect.getHeight(); @@ -80,11 +80,14 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)  		S32 requiredTextHeight = message->getTextBoundingRect().getHeight();  		S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); -		//Calculate last delta height deducting previous heightDelta  -		heightDelta = newTextHeight - oldTextHeight - heightDelta; +		heightDelta = newTextHeight - oldTextHeight; +		S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT);  		//reshape the panel with new height -		reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); +		if (new_panel_height != getRect().getHeight()) +		{ +			reshape( getRect().getWidth(), new_panel_height); +		}  	}  } @@ -98,7 +101,7 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification(  	if ("notifytip" == notification->getType())  	{  		// if it is online/offline notification -		if ("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName()) +		if ("FriendOnlineOffline" == notification->getName())  		{  			res = new LLPanelOnlineStatus(notification);  		} diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index 346e014d73..c22557206b 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -33,19 +33,13 @@  #include <string> -class LLToastPanelBase: public LLPanel  -{ -public: -	virtual void init(LLSD& data){}; -}; -  /**   * Base class for all panels that can be added to the toast.   * All toast panels should contain necessary logic for representing certain notification   * but shouldn't contain logic related to this panel lifetime control and positioning   * on the parent view.   */ -class LLToastPanel: public LLPanel { +class LLToastPanel : public LLPanel {  public:  	LLToastPanel(const LLNotificationPtr&);  	virtual ~LLToastPanel() = 0; diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp index feeb8ca77b..91ba8c0247 100644 --- a/indra/newview/lltoastscriptquestion.cpp +++ b/indra/newview/lltoastscriptquestion.cpp @@ -66,8 +66,8 @@ void LLToastScriptQuestion::snapToMessageHeight()  	if (mMessage->getVisible() && mFooter->getVisible())  	{  		S32 heightDelta = 0; -		S32 maxTextHeight = (mMessage->getDefaultFont()->getLineHeight() * MAX_LINES_COUNT) -						  + (mFooter->getDefaultFont()->getLineHeight() * MAX_LINES_COUNT); +		S32 maxTextHeight = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT) +						  + (mFooter->getFont()->getLineHeight() * MAX_LINES_COUNT);  		LLRect messageRect = mMessage->getRect();  		LLRect footerRect  = mFooter->getRect(); diff --git a/indra/newview/lltoastscripttextbox.cpp b/indra/newview/lltoastscripttextbox.cpp index 2529ec865a..45fbabad59 100644 --- a/indra/newview/lltoastscripttextbox.cpp +++ b/indra/newview/lltoastscripttextbox.cpp @@ -65,7 +65,7 @@ LLToastScriptTextbox::LLToastScriptTextbox(const LLNotificationPtr& notification  	pMessageText->clear();  	LLStyle::Params style; -	style.font = pMessageText->getDefaultFont(); +	style.font = pMessageText->getFont();  	pMessageText->appendText(message, TRUE, style);  	//submit button diff --git a/indra/newview/lltoastscripttextbox.h b/indra/newview/lltoastscripttextbox.h index 8e69d8834d..7d33446248 100644 --- a/indra/newview/lltoastscripttextbox.h +++ b/indra/newview/lltoastscripttextbox.h @@ -39,8 +39,6 @@ class LLToastScriptTextbox  public:  	void close(); -	static bool onNewNotification(const LLSD& notification); -  	// Non-transient messages.  You can specify non-default button  	// layouts (like one for script dialogs) by passing various  	// numbers in for "layout". diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index 81ad96f39e..2b5acdc1e8 100644 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -603,7 +603,7 @@ BOOL LLToolBarView::handleDragTool( S32 x, S32 y, const LLUUID& uuid, LLAssetTyp  BOOL LLToolBarView::handleDropTool( void* cargo_data, S32 x, S32 y, LLToolBar* toolbar)  {  	BOOL handled = FALSE; -	LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; +	LLInventoryObject* inv_item = static_cast<LLInventoryObject*>(cargo_data);  	LLAssetType::EType type = inv_item->getType();  	if (type == LLAssetType::AT_WIDGET) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index c69999981c..94c97158a8 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -58,7 +58,6 @@  #include "llviewerwindow.h"  #include "llvoavatarself.h"  #include "llworld.h" -#include "llclipboard.h"  // syntactic sugar  #define callMemberFunction(object,ptrToMember)  ((object).*(ptrToMember)) @@ -654,33 +653,41 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  		sOperationId++;  	} +	// For people drag and drop we don't need an actual inventory object, +	// instead we need the current cargo id, which should be a person id. +	bool is_uuid_dragged = (mSource == SOURCE_PEOPLE); +  	if (top_view)  	{  		handled = TRUE;  		for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)  		{ -			LLInventoryObject* cargo = locateInventory(item, cat); +			S32 local_x, local_y; +			top_view->screenPointToLocal( x, y, &local_x, &local_y ); +			EAcceptance item_acceptance = ACCEPT_NO; +			LLInventoryObject* cargo = locateInventory(item, cat);  			if (cargo)  			{ -				S32 local_x, local_y; -				top_view->screenPointToLocal( x, y, &local_x, &local_y ); -				EAcceptance item_acceptance = ACCEPT_NO;  				handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE,  													mCargoTypes[mCurItemIndex],  													(void*)cargo,  													&item_acceptance,  													mToolTipMsg); -				if (handled) -				{ -					// use sort order to determine priority of acceptance -					*acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); -				}  			} -			else +			else if (is_uuid_dragged)  			{ -				return;		 +				handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, +													mCargoTypes[mCurItemIndex], +													(void*)&mCargoIDs[mCurItemIndex], +													&item_acceptance, +													mToolTipMsg); +			} +			if (handled) +			{ +				// use sort order to determine priority of acceptance +				*acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance);  			}  		} @@ -697,20 +704,27 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  			for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)  			{ -				LLInventoryObject* cargo = locateInventory(item, cat); +				S32 local_x, local_y; +				EAcceptance item_acceptance; +				top_view->screenPointToLocal( x, y, &local_x, &local_y ); +				LLInventoryObject* cargo = locateInventory(item, cat);  				if (cargo)  				{ -					S32 local_x, local_y; - -					EAcceptance item_acceptance; -					top_view->screenPointToLocal( x, y, &local_x, &local_y );  					handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, TRUE,  														mCargoTypes[mCurItemIndex],  														(void*)cargo,  														&item_acceptance,  														mToolTipMsg);  				} +				else if (is_uuid_dragged) +				{ +					handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, +														mCargoTypes[mCurItemIndex], +														(void*)&mCargoIDs[mCurItemIndex], +														&item_acceptance, +														mToolTipMsg); +				}  			}  		}  		if (handled) @@ -727,17 +741,27 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  		for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)  		{ +			EAcceptance item_acceptance = ACCEPT_NO; +  			LLInventoryObject* cargo = locateInventory(item, cat);  			// fix for EXT-3191 -			if (NULL == cargo) return; - -			EAcceptance item_acceptance = ACCEPT_NO; -			handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, -												mCargoTypes[mCurItemIndex], -												(void*)cargo, -												&item_acceptance, -												mToolTipMsg); +			if (cargo) +			{ +				handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, +													mCargoTypes[mCurItemIndex], +													(void*)cargo, +													&item_acceptance, +													mToolTipMsg); +			} +			else if (is_uuid_dragged) +			{ +				handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, +													mCargoTypes[mCurItemIndex], +													(void*)&mCargoIDs[mCurItemIndex], +													&item_acceptance, +													mToolTipMsg); +			}  			if (handled)  			{  				// use sort order to determine priority of acceptance @@ -757,17 +781,25 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  			for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)  			{ -				LLInventoryObject* cargo = locateInventory(item, cat); +				EAcceptance item_acceptance; +				LLInventoryObject* cargo = locateInventory(item, cat);  				if (cargo)  				{ -					EAcceptance item_acceptance;  					handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE,  											  mCargoTypes[mCurItemIndex],  											  (void*)cargo,  											  &item_acceptance,  											  mToolTipMsg);  				} +				else if (is_uuid_dragged) +				{ +					handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, +											  mCargoTypes[mCurItemIndex], +											  (void*)&mCargoIDs[mCurItemIndex], +											  &item_acceptance, +											  mToolTipMsg); +				}  			}  		} @@ -780,7 +812,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  	if (!handled)  	{  		// Disallow drag and drop to 3D from the outbox -		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); +		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);  		if (outbox_id.notNull())  		{  			for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) @@ -2509,7 +2541,13 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory(  {  	item = NULL;  	cat = NULL; -	if(mCargoIDs.empty()) return NULL; + +	if (mCargoIDs.empty() +		|| (mSource == SOURCE_PEOPLE)) ///< There is no inventory item for people drag and drop. +	{ +		return NULL; +	} +  	if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))  	{  		// The object should be in user inventory. @@ -2545,6 +2583,7 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory(  	{  		item = (LLViewerInventoryItem*)gToolBarView->getDragItem();  	} +  	if(item) return item;  	if(cat) return cat;  	return NULL; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 41aee484db..f17300a76a 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -67,7 +67,8 @@ public:  		SOURCE_WORLD,  		SOURCE_NOTECARD,  		SOURCE_LIBRARY, -		SOURCE_VIEWER +		SOURCE_VIEWER, +		SOURCE_PEOPLE  	};  	void beginDrag(EDragAndDropType type, diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index a4b1c2155f..08ba5a5f25 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -83,6 +83,8 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()  	addEntry(LLViewerAssetType::AT_WIDGET, 				new ViewerAssetEntry(DAD_WIDGET)); +	addEntry(LLViewerAssetType::AT_PERSON, 				new ViewerAssetEntry(DAD_PERSON)); +  	addEntry(LLViewerAssetType::AT_NONE, 				new ViewerAssetEntry(DAD_NONE));  }; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 1f7cf0cdd4..50735d10bd 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -50,6 +50,8 @@  #include "llfloaterbump.h"  #include "llfloaterbvhpreview.h"  #include "llfloatercamera.h" +#include "llfloaterconversationlog.h" +#include "llfloaterconversationpreview.h"  #include "llfloaterdeleteenvpreset.h"  #include "llfloaterdisplayname.h"  #include "llfloatereditdaycycle.h" @@ -114,6 +116,7 @@  #include "llfloatertranslationsettings.h"  #include "llfloateruipreview.h"  #include "llfloatervoiceeffect.h" +#include "llfloatervoicevolume.h"  #include "llfloaterwhitelistentry.h"  #include "llfloaterwindowsize.h"  #include "llfloaterworldmap.h" @@ -137,7 +140,6 @@  #include "llscriptfloater.h"  #include "llfloatermodelpreview.h"  #include "llcommandhandler.h" -#include "llnearbychatbar.h"  // *NOTE: Please add files in alphabetical order to keep merges easy. @@ -190,9 +192,9 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>);  	LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); -	LLFloaterReg::add("chat_bar", "floater_chat_bar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChatBar>); - +	LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>);  	LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); +	LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>);  	LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>); @@ -224,6 +226,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLInspectGroupUtil::registerFloater();  	LLInspectObjectUtil::registerFloater();  	LLInspectRemoteObjectUtil::registerFloater(); +	LLFloaterVoiceVolumeUtil::registerFloater();  	LLNotificationsUI::registerFloater();  	LLFloaterDisplayNameUtil::registerFloater(); @@ -268,6 +271,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("picks", "floater_picks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);  	LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>);  	LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewAnim>, "preview"); +	LLFloaterReg::add("preview_conversation", "floater_conversation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationPreview>);  	LLFloaterReg::add("preview_gesture", "floater_preview_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewGesture>, "preview");  	LLFloaterReg::add("preview_notecard", "floater_preview_notecard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewNotecard>, "preview");  	LLFloaterReg::add("preview_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewLSL>, "preview"); diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index a32a78cbf9..c7d37e102e 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -40,7 +40,7 @@  #include "llviewermessage.h" // send_guid_sound_trigger  #include "llviewernetwork.h"  #include "llagent.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  // Globals  LLViewerGestureList gGestureList; @@ -130,7 +130,7 @@ void LLViewerGesture::doTrigger( BOOL send_chat )  	{  		// Don't play nodding animation, since that might not blend  		// with the gesture animation. -		LLNearbyChatBar::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); +		LLNearbyChat::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE);  	}  } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index b47a41c44c..a187318eb7 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1030,12 +1030,7 @@ void CreateGestureCallback::fire(const LLUUID& inv_item)  	gFloaterView->adjustToFitScreen(preview, FALSE);  } -void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) -{ -	if (mTargetLandmarkId.isNull()) return; -	gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); -}  LLInventoryCallbackManager gInventoryCallbacks; @@ -1308,7 +1303,7 @@ const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably  const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)  // ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... -void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) +void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid)  {  	std::string type_name = userdata.asString(); @@ -1332,7 +1327,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons  		LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null);  		gInventory.notifyObservers(); -		root->setSelectionByID(category, TRUE); +		panel->setSelectionByID(category, TRUE);  	}  	else if ("lsl" == type_name)  	{ @@ -1375,7 +1370,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons  			llwarns << "Can't create unrecognized type " << type_name << llendl;  		}  	} -	root->setNeedsAutoRename(TRUE);	 +	panel->getRootFolder()->setNeedsAutoRename(TRUE);	  }  LLAssetType::EType LLViewerInventoryItem::getType() const @@ -1449,348 +1444,6 @@ const std::string& LLViewerInventoryItem::getName() const  	return  LLInventoryItem::getName();  } -/** - * Class to store sorting order of favorites landmarks in a local file. EXT-3985. - * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. - * Data are stored in user home directory. - */ -class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> -	, public LLDestroyClass<LLFavoritesOrderStorage> -{ -	LOG_CLASS(LLFavoritesOrderStorage); -public: -	/** -	 * Sets sort index for specified with LLUUID favorite landmark -	 */ -	void setSortIndex(const LLUUID& inv_item_id, S32 sort_index); - -	/** -	 * Gets sort index for specified with LLUUID favorite landmark -	 */ -	S32 getSortIndex(const LLUUID& inv_item_id); -	void removeSortIndex(const LLUUID& inv_item_id); - -	void getSLURL(const LLUUID& asset_id); - -	/** -	 * Implementation of LLDestroyClass. Calls cleanup() instance method. -	 * -	 * It is important this callback is called before gInventory is cleaned. -	 * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), -	 * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. -	 * @see cleanup() -	 */ -	static void destroyClass(); - -	const static S32 NO_INDEX; -private: -	friend class LLSingleton<LLFavoritesOrderStorage>; -	LLFavoritesOrderStorage() : mIsDirty(false) { load(); } -	~LLFavoritesOrderStorage() { save(); } - -	/** -	 * Removes sort indexes for items which are not in Favorites bar for now. -	 */ -	void cleanup(); - -	const static std::string SORTING_DATA_FILE_NAME; - -	void load(); -	void save(); - -	void saveFavoritesSLURLs(); - -	// Remove record of current user's favorites from file on disk. -	void removeFavoritesRecordOfUser(); - -	void onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark); -	void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); - -	typedef std::map<LLUUID, S32> sort_index_map_t; -	sort_index_map_t mSortIndexes; - -	typedef std::map<LLUUID, std::string> slurls_map_t; -	slurls_map_t mSLURLs; - -	bool mIsDirty; - -	struct IsNotInFavorites -	{ -		IsNotInFavorites(const LLInventoryModel::item_array_t& items) -			: mFavoriteItems(items) -		{ - -		} - -		/** -		 * Returns true if specified item is not found among inventory items -		 */ -		bool operator()(const sort_index_map_t::value_type& id_index_pair) const -		{ -			LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first); -			if (item.isNull()) return true; - -			LLInventoryModel::item_array_t::const_iterator found_it = -				std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); - -			return found_it == mFavoriteItems.end(); -		} -	private: -		LLInventoryModel::item_array_t mFavoriteItems; -	}; - -}; - -const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; -const S32 LLFavoritesOrderStorage::NO_INDEX = -1; - -void LLFavoritesOrderStorage::setSortIndex(const LLUUID& inv_item_id, S32 sort_index) -{ -	mSortIndexes[inv_item_id] = sort_index; -	mIsDirty = true; -} - -S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) -{ -	sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); -	if (it != mSortIndexes.end()) -	{ -		return it->second; -	} -	return NO_INDEX; -} - -void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) -{ -	mSortIndexes.erase(inv_item_id); -	mIsDirty = true; -} - -void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) -{ -	slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); -	if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached - -	LLLandmark* lm = gLandmarkList.getAsset(asset_id, -			boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); -	if (lm) -	{ -		onLandmarkLoaded(asset_id, lm); -	} -} - -// static -void LLFavoritesOrderStorage::destroyClass() -{ -	LLFavoritesOrderStorage::instance().cleanup(); -	if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) -	{ -		LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); -	} -	else -	{ -		LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); -	} -} - -void LLFavoritesOrderStorage::load() -{ -	// load per-resident sorting information -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); - -	LLSD settings_llsd; -	llifstream file; -	file.open(filename); -	if (file.is_open()) -	{ -		LLSDSerialize::fromXML(settings_llsd, file); -	} - -	for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); -		iter != settings_llsd.endMap(); ++iter) -	{ -		mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); -	} -} - -void LLFavoritesOrderStorage::saveFavoritesSLURLs() -{ -	// Do not change the file if we are not logged in yet. -	if (!LLLoginInstance::getInstance()->authSuccess()) -	{ -		llwarns << "Cannot save favorites: not logged in" << llendl; -		return; -	} -	 -	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); -	if (user_dir.empty()) -	{ -		llwarns << "Cannot save favorites: empty user dir name" << llendl; -		return; -	} - -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); -	llifstream in_file; -	in_file.open(filename); -	LLSD fav_llsd; -	if (in_file.is_open()) -	{ -		LLSDSerialize::fromXML(fav_llsd, in_file); -	} - -	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - -	LLSD user_llsd; -	for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) -	{ -		LLSD value; -		value["name"] = (*it)->getName(); -		value["asset_id"] = (*it)->getAssetUUID(); - -		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); -		if (slurl_iter != mSLURLs.end()) -		{ -			lldebugs << "Saving favorite: idx=" << (*it)->getSortField() << ", SLURL=" <<  slurl_iter->second << ", value=" << value << llendl; -			value["slurl"] = slurl_iter->second; -			user_llsd[(*it)->getSortField()] = value; -		} -		else -		{ -			llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; -		} -	} - -	LLAvatarName av_name; -	LLAvatarNameCache::get( gAgentID, &av_name ); -	lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; -	fav_llsd[av_name.getLegacyName()] = user_llsd; - -	llofstream file; -	file.open(filename); -	LLSDSerialize::toPrettyXML(fav_llsd, file); -} - -void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() -{ -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); -	LLSD fav_llsd; -	llifstream file; -	file.open(filename); -	if (!file.is_open()) return; -	LLSDSerialize::fromXML(fav_llsd, file); - -	LLAvatarName av_name; -	LLAvatarNameCache::get( gAgentID, &av_name ); -	lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; -	if (fav_llsd.has(av_name.getLegacyName())) -	{ -		fav_llsd.erase(av_name.getLegacyName()); -	} - -	llofstream out_file; -	out_file.open(filename); -	LLSDSerialize::toPrettyXML(fav_llsd, out_file); - -} - -void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) -{ -	if (!landmark) return; - -	LLVector3d pos_global; -	if (!landmark->getGlobalPos(pos_global)) -	{ -		// If global position was unknown on first getGlobalPos() call -		// it should be set for the subsequent calls. -		landmark->getGlobalPos(pos_global); -	} - -	if (!pos_global.isExactlyZero()) -	{ -		LLLandmarkActions::getSLURLfromPosGlobal(pos_global, -				boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); -	} -} - -void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) -{ -	lldebugs << "Saving landmark SLURL: " << slurl << llendl; -	mSLURLs[asset_id] = slurl; -} - -void LLFavoritesOrderStorage::save() -{ -	// nothing to save if clean -	if (!mIsDirty) return; - -	// If we quit from the login screen we will not have an SL account -	// name.  Don't try to save, otherwise we'll dump a file in -	// C:\Program Files\SecondLife\ or similar. JC -	std::string user_dir = gDirUtilp->getLindenUserDir(); -	if (!user_dir.empty()) -	{ -		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); -		LLSD settings_llsd; - -		for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) -		{ -			settings_llsd[iter->first.asString()] = iter->second; -		} - -		llofstream file; -		file.open(filename); -		LLSDSerialize::toPrettyXML(settings_llsd, file); -	} -} - -void LLFavoritesOrderStorage::cleanup() -{ -	// nothing to clean -	if (!mIsDirty) return; - -	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - -	IsNotInFavorites is_not_in_fav(items); - -	sort_index_map_t  aTempMap; -	//copy unremoved values from mSortIndexes to aTempMap -	std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),  -		inserter(aTempMap, aTempMap.begin()), -		is_not_in_fav); - -	//Swap the contents of mSortIndexes and aTempMap -	mSortIndexes.swap(aTempMap); -} - - -S32 LLViewerInventoryItem::getSortField() const -{ -	return LLFavoritesOrderStorage::instance().getSortIndex(mUUID); -} - -void LLViewerInventoryItem::setSortField(S32 sortField) -{ -	LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); -	getSLURL(); -} - -void LLViewerInventoryItem::getSLURL() -{ -	LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); -} - -const LLPermissions& LLViewerInventoryItem::getPermissions() const -{ -	// Use the actual permissions of the symlink, not its parent. -	return LLInventoryItem::getPermissions();	 -} -  const LLUUID& LLViewerInventoryItem::getCreatorUUID() const  {  	if (const LLViewerInventoryItem *linked_item = getLinkedItem()) @@ -1861,17 +1514,6 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const  	return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK);  } - -time_t LLViewerInventoryItem::getCreationDate() const -{ -	return LLInventoryItem::getCreationDate(); -} - -U32 LLViewerInventoryItem::getCRC32() const -{ -	return LLInventoryItem::getCRC32();	 -} -  // *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985  static char getSeparator() { return '@'; }  BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 7822ef4da6..3cf03c3bc5 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -34,7 +34,7 @@  #include <boost/signals2.hpp>	// boost::signals2::trackable -class LLFolderView; +class LLInventoryPanel;  class LLFolderBridge;  class LLViewerInventoryCategory; @@ -60,10 +60,6 @@ public:  	virtual const LLUUID& getAssetUUID() const;  	virtual const LLUUID& getProtectedAssetUUID() const; // returns LLUUID::null if current agent does not have permission to expose this asset's UUID to the user  	virtual const std::string& getName() const; -	virtual S32 getSortField() const; -	virtual void setSortField(S32 sortField); -	virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here. -	virtual const LLPermissions& getPermissions() const;  	virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied  	virtual const LLUUID& getCreatorUUID() const;  	virtual const std::string& getDescription() const; @@ -72,8 +68,11 @@ public:  	virtual bool isWearableType() const;  	virtual LLWearableType::EType getWearableType() const;  	virtual U32 getFlags() const; -	virtual time_t getCreationDate() const; -	virtual U32 getCRC32() const; // really more of a checksum. + +    using LLInventoryItem::getPermissions; +	using LLInventoryItem::getCreationDate; +	using LLInventoryItem::setCreationDate; +	using LLInventoryItem::getCRC32;  	static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName); @@ -285,18 +284,6 @@ public:  	void fire(const LLUUID& inv_item);  }; -class AddFavoriteLandmarkCallback : public LLInventoryCallback -{ -public: -	AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} -	void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } - -private: -	void fire(const LLUUID& inv_item); - -	LLUUID mTargetLandmarkId; -}; -  // misc functions  //void inventory_reliable_callback(void**, S32 status); @@ -372,7 +359,7 @@ void copy_inventory_from_notecard(const LLUUID& destination_id,  								  U32 callback_id = 0); -void menu_create_inventory_item(LLFolderView* root, +void menu_create_inventory_item(LLInventoryPanel* root,  								LLFolderBridge* bridge,  								const LLSD& userdata,  								const LLUUID& default_parent_uuid = LLUUID::null); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 1aa9fd8a45..385d3cd29a 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -31,7 +31,7 @@  #include "llmath.h"  #include "llagent.h"  #include "llagentcamera.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llviewercontrol.h"  #include "llfocusmgr.h"  #include "llmorphview.h" @@ -534,7 +534,7 @@ void stop_moving( EKeystate s )  void start_chat( EKeystate s )  {  	// start chat -	LLNearbyChatBar::startChat(NULL); +	LLNearbyChat::startChat(NULL);  }  void start_gesture( EKeystate s ) @@ -543,15 +543,15 @@ void start_gesture( EKeystate s )  	if (KEYSTATE_UP == s &&  		! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))  	{ - 		if (LLNearbyChatBar::getInstance()->getCurrentChat().empty()) + 		if (LLNearbyChat::getInstance()->getCurrentChat().empty())   		{   			// No existing chat in chat editor, insert '/' - 			LLNearbyChatBar::startChat("/"); + 			LLNearbyChat::startChat("/");   		}   		else   		{   			// Don't overwrite existing text in chat editor - 			LLNearbyChatBar::startChat(NULL); + 			LLNearbyChat::startChat(NULL);   		}  	}  } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 01a54509ef..a993d195b5 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3263,15 +3263,6 @@ bool enable_freeze_eject(const LLSD& avatar_id)  	return new_value;  } - -void login_done(S32 which, void *user) -{ -	llinfos << "Login done " << which << llendl; - -	LLPanelLogin::closePanel(); -} - -  bool callback_leave_group(const LLSD& notification, const LLSD& response)  {  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 903f4437a7..b20b86a582 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -184,6 +184,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);  	LLMessageSystem* msg = gMessageSystem;  	const LLSD& payload = notification["payload"]; +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());  	// add friend to recent people list  	LLRecentPeople::instance().add(payload["from_id"]); @@ -209,7 +210,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  		msg->sendReliable(LLHost(payload["sender"].asString()));  		LLSD payload = notification["payload"]; -		payload["SUPPRESS_TOAST"] = true;  		LLNotificationsUtil::add("FriendshipAcceptedByMe",  				notification["substitutions"], payload);  		break; @@ -217,7 +217,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	case 1: // Decline  	{  		LLSD payload = notification["payload"]; -		payload["SUPPRESS_TOAST"] = true;  		LLNotificationsUtil::add("FriendshipDeclinedByMe",  				notification["substitutions"], payload);  	} @@ -246,6 +245,12 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  		break;  	} +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +	modified_form->setElementEnabled("Accept", false); +	modified_form->setElementEnabled("Decline", false); +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  }  static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback); @@ -726,7 +731,7 @@ static void highlight_inventory_objects_in_panel(const std::vector<LLUUID>& item  		LLFolderView* fv = inventory_panel->getRootFolder();  		if (fv)  		{ -			LLFolderViewItem* fv_item = fv->getItemByID(item_id); +			LLFolderViewItem* fv_item = inventory_panel->getItemByID(item_id);  			if (fv_item)  			{  				LLFolderViewItem* fv_folder = fv_item->getParentFolder(); @@ -814,7 +819,13 @@ private:  		mSelectedItems.clear();  		if (LLInventoryPanel::getActiveInventoryPanel())  		{ -			mSelectedItems = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); +			std::set<LLFolderViewItem*> selection =    LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); +			for (std::set<LLFolderViewItem*>::iterator it = selection.begin(),    end_it = selection.end(); +				it != end_it; +				++it) +			{ +				mSelectedItems.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +			}  		}  		mSelectedItems.erase(mMoveIntoFolderID);  	} @@ -849,7 +860,15 @@ private:  		}  		// get selected items (without destination folder) -		selected_items_t selected_items = active_panel->getRootFolder()->getSelectionList(); +		selected_items_t selected_items; + 		 + 		std::set<LLFolderViewItem*> selection =    LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); +		for (std::set<LLFolderViewItem*>::iterator it = selection.begin(),    end_it = selection.end(); +			it != end_it; +			++it) +		{ +			selected_items.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +		}  		selected_items.erase(mMoveIntoFolderID);  		// compare stored & current sets of selected items @@ -1155,7 +1174,7 @@ bool check_offer_throttle(const std::string& from_name, bool check_only)  		}  	}  } - +   // Return "true" if we have a preview method for that asset type, "false" otherwise  bool check_asset_previewable(const LLAssetType::EType asset_type)  { @@ -1478,16 +1497,15 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  		itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);  	} +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); +	  	// For muting, we need to add the mute, then decline the offer.  	// This must be done here because:  	// * callback may be called immediately,  	// * adding the mute sends a message,  	// * we can't build two messages at once. -	if (2 == button) // Block +	if (IOR_MUTE == button) // Block  	{ -		LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - -		llassert(notification_ptr != NULL);  		if (notification_ptr != NULL)  		{  			gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3)); @@ -1502,6 +1520,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	bool busy = gAgent.getBusy(); +	LLNotificationFormPtr modified_form(notification_ptr ? new LLNotificationForm(*notification_ptr->getForm()) : new LLNotificationForm()); +  	switch(button)  	{  	case IOR_SHOW: @@ -1545,6 +1565,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;  			break;  		} + +		if (modified_form != NULL) +		{ +			modified_form->setElementEnabled("Show", false); +		}  		break;  		// end switch (mIM) @@ -1557,9 +1582,14 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			args["MESSAGE"] = log_message;  			LLNotificationsUtil::add("SystemMessageTip", args);  		} +  		break;  	case IOR_MUTE: +		if (modified_form != NULL) +		{ +			modified_form->setElementEnabled("Mute", false); +		}  		// MUTE falls through to decline  	case IOR_DECLINE:  		{ @@ -1595,6 +1625,13 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			{  				busy_message(gMessageSystem, mFromID);  			} + +			if (modified_form != NULL) +			{ +				modified_form->setElementEnabled("Show", false); +				modified_form->setElementEnabled("Discard", false); +			} +  			break;  		}  	default: @@ -1614,6 +1651,13 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	{  		delete this;  	} + +	if (notification_ptr != NULL) +	{ +		notification_ptr->updateForm(modified_form); +		notification_ptr->repost(); +	} +  	return false;  } @@ -1991,6 +2035,15 @@ bool lure_callback(const LLSD& notification, const LLSD& response)  					   lure_id);  		break;  	} + +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); + +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +	modified_form->setElementEnabled("Teleport", false); +	modified_form->setElementEnabled("Cancel", false); +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  }  static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); @@ -2386,6 +2439,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				from_id,  				name,  				buffer, +				IM_OFFLINE == offline,  				LLStringUtil::null,  				dialog,  				parent_estate_id, @@ -2420,12 +2474,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;  			bool mute_im = is_muted; -			if (accept_im_from_only_friend && !is_friend) +			if(accept_im_from_only_friend&&!is_friend)  			{  				if (!gIMMgr->isNonFriendSessionNotified(session_id))  				{  					std::string message = LLTrans::getString("IM_unblock_only_groups_friends"); -					gIMMgr->addMessage(session_id, from_id, name, message); +					gIMMgr->addMessage(session_id, from_id, name, message, IM_OFFLINE == offline);  					gIMMgr->addNotifiedNonFriendSessionID(session_id);  				} @@ -2438,6 +2492,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  					from_id,  					name,  					buffer, +					IM_OFFLINE == offline,  					LLStringUtil::null,  					dialog,  					parent_estate_id, @@ -2778,6 +2833,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			from_id,  			name,  			buffer, +			IM_OFFLINE == offline,  			ll_safe_string((char*)binary_bucket),  			IM_SESSION_INVITE,  			parent_estate_id, @@ -2847,7 +2903,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				chat.mOwnerID = from_id;  				LLSD args;  				args["slurl"] = location; -				args["type"] = LLNotificationsUI::NT_NEARBYCHAT;  				// Look for IRC-style emotes here so object name formatting is correct  				std::string prefix = message.substr(0, 4); @@ -3591,7 +3646,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)  		// pass owner_id to chat so that we can display the remote  		// object inspect for an object that is chatting with you  		LLSD args; -		args["type"] = LLNotificationsUI::NT_NEARBYCHAT;  		chat.mOwnerID = owner_id;  		if (gSavedSettings.getBOOL("TranslateChat") && chat.mSourceType != CHAT_SOURCE_SYSTEM) @@ -6798,7 +6852,6 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)  				//*TODO please rewrite all keys to the same case, lower or upper  				payload["from_id"] = target_id; -				payload["SUPPRESS_TOAST"] = true;  				LLNotificationsUtil::add("TeleportOfferSent", args, payload);  				// Add the recepient to the recent people list. diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 6c4e70add0..b2e6dc4571 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -237,7 +237,6 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe  	mTimeDilation(1.f),  	mRotTime(0.f),  	mAngularVelocityRot(), -	mJointInfo(NULL),  	mState(0),  	mMedia(NULL),  	mClickAction(0), @@ -283,12 +282,6 @@ LLViewerObject::~LLViewerObject()  		mInventory = NULL;  	} -	if (mJointInfo) -	{ -		delete mJointInfo; -		mJointInfo = NULL; -	} -  	if (mPartSourcep)  	{  		mPartSourcep->setDead(); @@ -339,9 +332,6 @@ void LLViewerObject::markDead()  		if (getParent())  		{  			((LLViewerObject *)getParent())->removeChild(this); -			// go ahead and delete any jointinfo's that we find -			delete mJointInfo; -			mJointInfo = NULL;  		}  		// Mark itself as dead @@ -744,7 +734,7 @@ void LLViewerObject::addThisAndNonJointChildren(std::vector<LLViewerObject*>& ob  		 iter != mChildList.end(); iter++)  	{  		LLViewerObject* child = *iter; -		if ( (!child->isAvatar()) && (!child->isJointChild())) +		if ( (!child->isAvatar()))  		{  			child->addThisAndNonJointChildren(objects);  		} @@ -794,7 +784,13 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)  	}  	LLDrawable* old_parent = mDrawable->mParent;  	mDrawable->mParent = parentp;  -		 +	 +	if (parentp && mDrawable->isActive()) +	{ +		parentp->makeActive(); +		parentp->setState(LLDrawable::ACTIVE_CHILD); +	} +  	gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);  	if(	(old_parent != parentp && old_parent)  		|| (parentp && parentp->isActive())) @@ -1297,26 +1293,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  					}  				} -				U8 joint_type = 0; -				mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_JointType, joint_type, block_num); -				if (joint_type) -				{ -					// create new joint info  -					if (!mJointInfo) -					{ -						mJointInfo = new LLVOJointInfo; -					} -					mJointInfo->mJointType = (EHavokJointType) joint_type; -					mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointPivot, mJointInfo->mPivot, block_num); -					mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointAxisOrAnchor, mJointInfo->mAxisOrAnchor, block_num); -				} -				else if (mJointInfo) -				{ -					// this joint info is no longer needed -					delete mJointInfo; -					mJointInfo = NULL; -				} -  				break;  			} @@ -1964,14 +1940,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  						cur_parentp->removeChild(this); -						if (mJointInfo && !parent_id) -						{ -							// since this object is no longer parent-relative -							// we make sure we delete any joint info -							delete mJointInfo; -							mJointInfo = NULL; -						} -  						setChanged(MOVED | SILHOUETTE);  						if (mDrawable.notNull()) @@ -2105,9 +2073,15 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  		gPipeline.addDebugBlip(getPositionAgent(), color);  	} -	if ((0.0f == vel_mag_sq) &&  -		(0.0f == accel_mag_sq) && -		(0.0f == getAngularVelocity().magVecSquared())) +	const F32 MAG_CUTOFF = F_APPROXIMATELY_ZERO; + +	llassert(vel_mag_sq >= 0.f); +	llassert(accel_mag_sq >= 0.f); +	llassert(getAngularVelocity().magVecSquared() >= 0.f); + +	if ((MAG_CUTOFF >= vel_mag_sq) &&  +		(MAG_CUTOFF >= accel_mag_sq) && +		(MAG_CUTOFF >= getAngularVelocity().magVecSquared()))  	{  		mStatic = TRUE; // This object doesn't move!  	} @@ -2178,117 +2152,36 @@ BOOL LLViewerObject::isActive() const -BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  {  	//static LLFastTimer::DeclareTimer ftm("Viewer Object");  	//LLFastTimer t(ftm); -	if (mDead) -	{ -		// It's dead.  Don't update it. -		return TRUE; -	} - -	// CRO - don't velocity interp linked objects! -	// Leviathan - but DO velocity interp joints -	if (!mStatic && sVelocityInterpolate && !isSelected()) +	if (!mDead)  	{ -		// calculate dt from last update -		F32 dt_raw = (F32)(time - mLastInterpUpdateSecs); -		F32 dt = mTimeDilation * dt_raw; - -		if (!mJointInfo) +		// CRO - don't velocity interp linked objects! +		// Leviathan - but DO velocity interp joints +		if (!mStatic && sVelocityInterpolate && !isSelected())  		{ -			applyAngularVelocity(dt); -		} +			// calculate dt from last update +			F32 dt_raw = (F32)(time - mLastInterpUpdateSecs); +			F32 dt = mTimeDilation * dt_raw; -		LLViewerObject *parentp = (LLViewerObject *) getParent(); -		if (mJointInfo) -		{ -			if (parentp) +			applyAngularVelocity(dt); +			 +			if (isAttachment())  			{ -				// do parent-relative stuff -				LLVector3 ang_vel = getAngularVelocity(); -				F32 omega = ang_vel.magVecSquared(); -				F32 angle = 0.0f; -				LLQuaternion dQ; -				if (omega > 0.00001f) -				{ -					omega = sqrt(omega); -					angle = omega * dt; -					dQ.setQuat(angle, ang_vel); -				} -				LLVector3 pos = getPosition(); -	 -				if (HJT_HINGE == mJointInfo->mJointType) -				{ -					// hinge = uniform circular motion -					LLVector3 parent_pivot = getVelocity(); -					LLVector3 parent_axis = getAcceleration(); -	 -					angle = dt * (ang_vel * mJointInfo->mAxisOrAnchor);	// AxisOrAnchor = axis -					dQ.setQuat(angle, mJointInfo->mAxisOrAnchor);		// AxisOrAnchor = axis -					LLVector3 pivot_offset = pos - mJointInfo->mPivot;	// pos in pivot-frame -					pivot_offset = pivot_offset * dQ;					// new rotated pivot-frame pos -					pos = mJointInfo->mPivot + pivot_offset;			// parent-frame -					LLViewerObject::setPosition(pos); -					LLQuaternion Q_PC = getRotation(); -					setRotation(Q_PC * dQ); -					mLastInterpUpdateSecs = time; -				} -				else if (HJT_POINT == mJointInfo->mJointType) -						// || HJT_LPOINT == mJointInfo->mJointType) -				{ -					// point-to-point = spin about axis and uniform circular motion -					// 					of axis about the pivot point -					// -					// NOTE: this interpolation scheme is not quite good enough to -					// reduce the bandwidth -- needs a gravitational correction.  -					// Similarly for hinges with axes that deviate from vertical. -	 -					LLQuaternion Q_PC = getRotation(); -					Q_PC = Q_PC * dQ; -					setRotation(Q_PC); - -					LLVector3 pivot_to_child = - mJointInfo->mAxisOrAnchor;	// AxisOrAnchor = anchor -					pos = mJointInfo->mPivot + pivot_to_child * Q_PC; -					LLViewerObject::setPosition(pos); -					mLastInterpUpdateSecs = time; -				} -				/* else if (HJT_WHEEL == mJointInfo->mJointInfo) -				{ -					// wheel = uniform rotation about axis, with linear -					//		   velocity interpolation (if any) -					LLVector3 parent_axis = getAcceleration();	// HACK -- accel stores the parent-axis (parent-frame) -	 -					LLQuaternion Q_PC = getRotation(); -	 -					angle = dt * (parent_axis * ang_vel); -					dQ.setQuat(angle, parent_axis); -	 -					Q_PC = Q_PC * dQ; -					setRotation(Q_PC); - -					pos = getPosition() + dt * getVelocity(); -					LLViewerObject::setPosition(pos); -					mLastInterpUpdateSecs = time; -				}*/ +				mLastInterpUpdateSecs = time; +				return; +			} +			else +			{	// Move object based on it's velocity and rotation +				interpolateLinearMotion(time, dt);  			}  		} -		else if (isAttachment()) -		{ -			mLastInterpUpdateSecs = time; -			return TRUE; -		} -		else -		{	// Move object based on it's velocity and rotation -			interpolateLinearMotion(time, dt); -		} -	} - -	updateDrawable(FALSE); -	return TRUE; +		updateDrawable(FALSE); +	}  } @@ -2967,6 +2860,21 @@ void LLViewerObject::updateInventory(  {  	LLMemType mt(LLMemType::MTYPE_OBJECT); +	std::list<LLUUID>::iterator begin = mPendingInventoryItemsIDs.begin(); +	std::list<LLUUID>::iterator end = mPendingInventoryItemsIDs.end(); + +	bool is_fetching = std::find(begin, end, item->getAssetUUID()) != end; +	bool is_fetched = getInventoryItemByAsset(item->getAssetUUID()) != NULL; + +	if (is_fetched || is_fetching) +	{ +		return; +	} +	else +	{ +		mPendingInventoryItemsIDs.push_back(item->getAssetUUID()); +	} +  	// This slices the object into what we're concerned about on the  	// viewer. The simulator will take the permissions and transfer  	// ownership. @@ -3878,15 +3786,6 @@ void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped)  		((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset);  		updateDrawable(damped);  	} -	else if (isJointChild()) -	{ -		// compute new parent-relative position -		LLViewerObject *parent = (LLViewerObject *) getParent(); -		LLQuaternion inv_parent_rot = parent->getRotation(); -		inv_parent_rot.transQuat(); -		LLVector3 pos_parent = (pos_edit - parent->getPositionRegion()) * inv_parent_rot; -		LLViewerObject::setPosition(pos_parent, damped); -	}  	else  	{  		LLViewerObject::setPosition(pos_edit, damped); @@ -3900,8 +3799,7 @@ LLViewerObject* LLViewerObject::getRootEdit() const  {  	const LLViewerObject* root = this;  	while (root->mParent  -		   && !(root->mJointInfo -			   || ((LLViewerObject*)root->mParent)->isAvatar()) ) +		   && !((LLViewerObject*)root->mParent)->isAvatar())   	{  		root = (LLViewerObject*)root->mParent;  	} @@ -4610,19 +4508,11 @@ void LLViewerObject::clearIcon()  LLViewerObject* LLViewerObject::getSubParent()   {  -	if (isJointChild()) -	{ -		return this; -	}  	return (LLViewerObject*) getParent();  }  const LLViewerObject* LLViewerObject::getSubParent() const  { -	if (isJointChild()) -	{ -		return this; -	}  	return (const LLViewerObject*) getParent();  } @@ -5492,8 +5382,11 @@ BOOL LLViewerObject::setFlagsWithoutUpdate(U32 flags, BOOL state)  void LLViewerObject::setPhysicsShapeType(U8 type)  {  	mPhysicsShapeUnknown = false; -	mPhysicsShapeType = type; -	mCostStale = true; +	if (type != mPhysicsShapeType) +	{ +		mPhysicsShapeType = type; +		mCostStale = true; +	}  }  void LLViewerObject::setPhysicsGravity(F32 gravity) @@ -5520,7 +5413,6 @@ U8 LLViewerObject::getPhysicsShapeType() const  {   	if (mPhysicsShapeUnknown)  	{ -		mPhysicsShapeUnknown = false;  		gObjectList.updatePhysicsFlags(this);  	} diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 05d017dee3..22e0de681e 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -88,18 +88,6 @@ typedef void (*inventory_callback)(LLViewerObject*,  								   S32 serial_num,  								   void*); -// a small struct for keeping track of joints -struct LLVOJointInfo -{ -	EHavokJointType mJointType; -	LLVector3 mPivot;			// parent-frame -	// whether the below an axis or anchor (and thus its frame) -	// depends on the joint type: -	//     HINGE   ==>   axis=parent-frame -	//     P2P     ==>   anchor=child-frame -	LLVector3 mAxisOrAnchor;	 -}; -  // for exporting textured materials from SL  struct LLMaterialExportInfo  { @@ -157,7 +145,7 @@ public:  	LLNameValue*	getNVPair(const std::string& name) const;			// null if no name value pair by that name  	// Object create and update functions -	virtual BOOL	idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	virtual void	idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	// Types of media we can associate  	enum { MEDIA_NONE = 0, MEDIA_SET = 1 }; @@ -188,8 +176,6 @@ public:  	virtual void 	updateRadius() {};  	virtual F32 	getVObjRadius() const; // default implemenation is mDrawable->getRadius() -	BOOL 			isJointChild() const { return mJointInfo ? TRUE : FALSE; }  -	EHavokJointType	getJointType() const { return mJointInfo ? mJointInfo->mJointType : HJT_INVALID; }  	// for jointed and other parent-relative hacks  	LLViewerObject* getSubParent();  	const LLViewerObject* getSubParent() const; @@ -740,7 +726,6 @@ protected:  	F32				mRotTime;					// Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega)  	LLQuaternion	mAngularVelocityRot;		// accumulated rotation from the angular velocity computations -	LLVOJointInfo*  mJointInfo;  	U8				mState;	// legacy  	LLViewerObjectMedia* mMedia;	// NULL if no media associated  	U8 mClickAction; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index ea20950b36..e399b45cba 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -49,6 +49,8 @@  #include "llstring.h"  #include "llhudnametag.h"  #include "lldrawable.h" +#include "llflexibleobject.h" +#include "llviewertextureanim.h"  #include "xform.h"  #include "llsky.h"  #include "llviewercamera.h" @@ -78,11 +80,9 @@  extern F32 gMinObjectDistance;  extern BOOL gAnimateTextures; -void dialog_refresh_all(); +#define MAX_CONCURRENT_PHYSICS_REQUESTS 256 -#define CULL_VIS -//#define ORPHAN_SPAM -//#define IGNORE_DEAD +void dialog_refresh_all();  // Global lists of objects - should go away soon.  LLViewerObjectList gObjectList; @@ -909,8 +909,6 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  	const F64 frame_time = LLFrameTimer::getElapsedSeconds(); -	std::vector<LLViewerObject*> kill_list; -	S32 num_active_objects = 0;  	LLViewerObject *objectp = NULL;	  	// Make a copy of the list in case something in idleUpdate() messes with it @@ -950,7 +948,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  	std::vector<LLViewerObject*>::iterator idle_end = idle_list.begin()+idle_count;  	if (gSavedSettings.getBOOL("FreezeTime")) -	{ +	{	  		for (std::vector<LLViewerObject*>::iterator iter = idle_list.begin();  			iter != idle_end; iter++) @@ -968,24 +966,20 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  			idle_iter != idle_end; idle_iter++)  		{  			objectp = *idle_iter; -			if (objectp->idleUpdate(agent, world, frame_time)) -			{ -				num_active_objects++;				 -			} -			else -			{ -				//  If Idle Update returns false, kill object! -				kill_list.push_back(objectp); -			} -		} -		for (std::vector<LLViewerObject*>::iterator kill_iter = kill_list.begin(); -			kill_iter != kill_list.end(); kill_iter++) -		{ -			objectp = *kill_iter; -			killObject(objectp); +			llassert(objectp->isActive()); +			objectp->idleUpdate(agent, world, frame_time); +  		} + +		//update flexible objects +		LLVolumeImplFlexible::updateClass(); + +		//update animated textures +		LLViewerTextureAnim::updateClass();  	} + +  	fetchObjectCosts();  	fetchPhysicsFlags(); @@ -1052,7 +1046,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  	*/  	LLViewerStats::getInstance()->mNumObjectsStat.addValue((S32) mObjects.size()); -	LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(num_active_objects); +	LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(idle_count);  	LLViewerStats::getInstance()->mNumSizeCulledStat.addValue(mNumSizeCulled);  	LLViewerStats::getInstance()->mNumVisCulledStat.addValue(mNumVisCulled);  } @@ -1073,8 +1067,6 @@ void LLViewerObjectList::fetchObjectCosts()  				LLSD id_list;  				U32 object_index = 0; -				U32 count = 0; -  				for (  					std::set<LLUUID>::iterator iter = mStaleObjectCost.begin();  					iter != mStaleObjectCost.end(); @@ -1091,7 +1083,7 @@ void LLViewerObjectList::fetchObjectCosts()  					mStaleObjectCost.erase(iter++); -					if (count++ >= 450) +					if (object_index >= MAX_CONCURRENT_PHYSICS_REQUESTS)  					{  						break;  					} @@ -1136,7 +1128,7 @@ void LLViewerObjectList::fetchPhysicsFlags()  				for (  					std::set<LLUUID>::iterator iter = mStalePhysicsFlags.begin();  					iter != mStalePhysicsFlags.end(); -					++iter) +					)  				{  					// Check to see if a request for this object  					// has already been made. @@ -1146,12 +1138,14 @@ void LLViewerObjectList::fetchPhysicsFlags()  						mPendingPhysicsFlags.insert(*iter);  						id_list[object_index++] = *iter;  					} -				} -				// id_list should now contain all -				// requests in mStalePhysicsFlags before, so clear -				// it now -				mStalePhysicsFlags.clear(); +					mStalePhysicsFlags.erase(iter++); +					 +					if (object_index >= MAX_CONCURRENT_PHYSICS_REQUESTS) +					{ +						break; +					} +				}  				if ( id_list.size() > 0 )  				{ @@ -1405,8 +1399,9 @@ void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp)  		{  			mActiveObjects[idx] = mActiveObjects[last_index];  			mActiveObjects[idx]->setListIndex(idx); -			mActiveObjects.pop_back();  		} + +		mActiveObjects.pop_back();  	}  } @@ -1450,6 +1445,9 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp)  			objectp->setOnActiveList(FALSE);  		}  	} + +	llassert(objectp->isActive() || objectp->getListIndex() == -1); +  }  void LLViewerObjectList::updateObjectCost(LLViewerObject* object) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index d9918e633b..4b0e0598f6 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -529,9 +529,10 @@ void LLViewerShaderMgr::setShaders()  			{  				loaded = loadShadersInterface();  			} -			 +  			if (loaded) -			{ + +		    {  				loaded = loadTransformShaders();  			} diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 7f638a24bf..e1eb54bd24 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2182,7 +2182,8 @@ void LLViewerFetchedTexture::setIsMissingAsset()  	}  	else  	{ -		llwarns << mUrl << ": Marking image as missing" << llendl; +		//it is normal no map tile on an empty region. +		//llwarns << mUrl << ": Marking image as missing" << llendl;  	}  	if (mHasFetcher)  	{ diff --git a/indra/newview/llviewertextureanim.cpp b/indra/newview/llviewertextureanim.cpp index 9f1ac7c49c..2b364851a7 100644 --- a/indra/newview/llviewertextureanim.cpp +++ b/indra/newview/llviewertextureanim.cpp @@ -27,21 +27,37 @@  #include "llviewerprecompiledheaders.h"  #include "llviewertextureanim.h" +#include "llvovolume.h"  #include "llmath.h"  #include "llerror.h" -LLViewerTextureAnim::LLViewerTextureAnim() : LLTextureAnim() +std::vector<LLViewerTextureAnim*> LLViewerTextureAnim::sInstanceList; + +LLViewerTextureAnim::LLViewerTextureAnim(LLVOVolume* vobj) : LLTextureAnim()  { +	mVObj = vobj;  	mLastFrame = -1.f;	// Force an update initially  	mLastTime = 0.f;  	mOffS = mOffT = 0;  	mScaleS = mScaleT = 1;  	mRot = 0; + +	mInstanceIndex = sInstanceList.size(); +	sInstanceList.push_back(this);  }  LLViewerTextureAnim::~LLViewerTextureAnim()  { +	S32 end_idx = sInstanceList.size()-1; +	 +	if (end_idx != mInstanceIndex) +	{ +		sInstanceList[mInstanceIndex] = sInstanceList[end_idx]; +		sInstanceList[mInstanceIndex]->mInstanceIndex = mInstanceIndex; +	} + +	sInstanceList.pop_back();  }  void LLViewerTextureAnim::reset() @@ -50,6 +66,14 @@ void LLViewerTextureAnim::reset()  	mTimer.reset();  } +//static  +void LLViewerTextureAnim::updateClass() +{ +	for (std::vector<LLViewerTextureAnim*>::iterator iter = sInstanceList.begin(); iter != sInstanceList.end(); ++iter) +	{ +		(*iter)->mVObj->animateTextures(); +	} +}  S32 LLViewerTextureAnim::animateTextures(F32 &off_s, F32 &off_t,  										F32 &scale_s, F32 &scale_t, diff --git a/indra/newview/llviewertextureanim.h b/indra/newview/llviewertextureanim.h index dd7bd0cb90..abbfabceb9 100644 --- a/indra/newview/llviewertextureanim.h +++ b/indra/newview/llviewertextureanim.h @@ -30,10 +30,18 @@  #include "lltextureanim.h"  #include "llframetimer.h" +class LLVOVolume; +  class LLViewerTextureAnim : public LLTextureAnim  { +private: +	static std::vector<LLViewerTextureAnim*> sInstanceList; +	S32 mInstanceIndex; +  public: -	LLViewerTextureAnim(); +	static void updateClass(); + +	LLViewerTextureAnim(LLVOVolume* vobj);  	virtual ~LLViewerTextureAnim();  	/*virtual*/ void reset(); @@ -51,6 +59,7 @@ public:  	F32 mRot;  protected: +	LLVOVolume* mVObj;  	LLFrameTimer mTimer;  	F64 mLastTime;  	F32 mLastFrame; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index af2eec9ba8..1bcf15913f 100644..100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -56,6 +56,7 @@  // linden library includes  #include "llaudioengine.h"		// mute on minimize +#include "llchatentry.h"  #include "indra_constants.h"  #include "llassetstorage.h"  #include "llerrorcontrol.h" @@ -187,7 +188,7 @@  #include "llviewerjoystick.h"  #include "llviewernetwork.h"  #include "llpostprocess.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llagentui.h"  #include "llwearablelist.h" @@ -1550,11 +1551,12 @@ LLViewerWindow::LLViewerWindow(const Params& p)  	// boost::lambda::var() constructs such a functor on the fly.  	mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard)));  	mViewerWindowListener.reset(new LLViewerWindowListener(this)); -	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); -	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); -	LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert); -	LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert); +	mAlertsChannel.reset(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"))); +	mModalAlertsChannel.reset(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"))); + +	mAlertsChannel->connectChanged(&LLViewerWindow::onAlert); +	mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert);  	LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));  	llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl; @@ -2495,11 +2497,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	// Traverses up the hierarchy  	if( keyboard_focus )  	{ -		LLNearbyChatBar* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar"); +		LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar");  		if (nearby_chat)  		{ -			LLLineEditor* chat_editor = nearby_chat->getChatBox(); +			LLChatEntry* chat_editor = nearby_chat->getChatBox();  		// arrow keys move avatar while chatting hack  		if (chat_editor && chat_editor->hasFocus()) @@ -2562,11 +2564,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() &&   		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )  	{ -		LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar")->getChatBox(); +		LLChatEntry* chat_editor = LLNearbyChat::getInstance()->getChatBox();  		if (chat_editor)  		{  			// passing NULL here, character will be added later when it is handled by character handler. -			LLNearbyChatBar::getInstance()->startChat(NULL); +			LLNearbyChat::getInstance()->startChat(NULL);  			return TRUE;  		}  	} diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 6efcaeaf18..ee6a7793f8 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -418,6 +418,9 @@ private:  	bool			mActive;  	bool			mUIVisible; +	boost::shared_ptr<class LLNotificationChannel>	mAlertsChannel, +													mModalAlertsChannel; +  	LLRect			mWindowRectRaw;				// whole window, including UI  	LLRect			mWindowRectScaled;			// whole window, scaled by UI size  	LLRect			mWorldViewRectRaw;			// area of screen for 3D world diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 05febdf93b..7b08744598 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -34,6 +34,8 @@  #include "llvoavatar.h" +#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot +  #include <stdio.h>  #include <ctype.h> @@ -62,6 +64,7 @@  #include "llhudmanager.h"  #include "llhudnametag.h"  #include "llhudtext.h"				// for mText/mDebugText +#include "llinitparam.h"  #include "llkeyframefallmotion.h"  #include "llkeyframestandmotion.h"  #include "llkeyframewalkmotion.h" @@ -191,6 +194,9 @@ const S32 MAX_BUBBLE_CHAT_LENGTH = DB_CHAT_MSG_STR_LEN;  const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12;  const F32 CHAT_FADE_TIME = 8.0;  const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; +const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f; +const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; +const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f;  const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); @@ -222,55 +228,62 @@ struct LLTextureMaskData   **/  //------------------------------------------------------------------------ -// LLVOBoneInfo +// LLVOAvatarBoneInfo  // Trans/Scale/Rot etc. info about each avatar bone.  Used by LLVOAvatarSkeleton.  //------------------------------------------------------------------------ -class LLVOAvatarBoneInfo +struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block<LLVOAvatarCollisionVolumeInfo>  { -	friend class LLVOAvatar; -	friend class LLVOAvatarSkeletonInfo; -public: -	LLVOAvatarBoneInfo() : mIsJoint(FALSE) {} -	~LLVOAvatarBoneInfo() +	LLVOAvatarCollisionVolumeInfo()  +	:	name("name"), +		pos("pos"), +		rot("rot"), +		scale("scale") +	{} + +	Mandatory<std::string>	name; +	Mandatory<LLVector3>	pos, +							rot, +							scale; +}; + +struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint>  	{ -		std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); -	} -	BOOL parseXml(LLXmlTreeNode* node); +	Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_A_BLOCK> >	bone; +	Alternative<LLVOAvatarCollisionVolumeInfo>		collision_volume; -private: -	std::string mName; -	BOOL mIsJoint; -	LLVector3 mPos; -	LLVector3 mRot; -	LLVector3 mScale; -	LLVector3 mPivot; -	typedef std::vector<LLVOAvatarBoneInfo*> child_list_t; -	child_list_t mChildList; +	LLVOAvatarChildJoint() +	:	bone("bone"), +		collision_volume("collision_volume") +	{} +}; + +struct LLVOAvatarBoneInfo : public LLInitParam::Block<LLVOAvatarBoneInfo, LLVOAvatarCollisionVolumeInfo> +{ +	LLVOAvatarBoneInfo()  +	:	pivot("pivot") +	{} +	 +	Mandatory<LLVector3>					pivot; +	Multiple<LLVOAvatarChildJoint>			children;  };  //------------------------------------------------------------------------  // LLVOAvatarSkeletonInfo  // Overall avatar skeleton  //------------------------------------------------------------------------ -class LLVOAvatarSkeletonInfo +struct LLVOAvatarSkeletonInfo : public LLInitParam::Block<LLVOAvatarSkeletonInfo>  { -	friend class LLVOAvatar; -public: -	LLVOAvatarSkeletonInfo() : -		mNumBones(0), mNumCollisionVolumes(0) {} -	~LLVOAvatarSkeletonInfo() -	{ -		std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); -	} -	BOOL parseXml(LLXmlTreeNode* node); -	S32 getNumBones() const { return mNumBones; } -	S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } +	LLVOAvatarSkeletonInfo() +	:	skeleton_root(""), +		num_bones("num_bones"), +		num_collision_volumes("num_collision_volumes"), +		version("version") +	{} -private: -	S32 mNumBones; -	S32 mNumCollisionVolumes; -	typedef std::vector<LLVOAvatarBoneInfo*> bone_info_list_t; -	bone_info_list_t mBoneInfoList; +	Mandatory<std::string>			version; +	Mandatory<S32>					num_bones, +									num_collision_volumes; +	Mandatory<LLVOAvatarChildJoint>	skeleton_root;  };  //----------------------------------------------------------------------------- @@ -595,7 +608,7 @@ private:  // Static Data  //-----------------------------------------------------------------------------  LLXmlTree LLVOAvatar::sXMLTree; -LLXmlTree LLVOAvatar::sSkeletonXMLTree; +LLXMLNodePtr LLVOAvatar::sSkeletonXMLTree;  LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL;  LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL;  LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; @@ -698,9 +711,13 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	LLMemType mt(LLMemType::MTYPE_AVATAR);  	//VTResume();  // VTune +#ifdef XXX_STINSON_CHUI_REWORK  	// mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline  	const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job  	mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); +#else // XXX_STINSON_CHUI_REWORK +	mVoiceVisualizer = new LLVoiceVisualizer(); +#endif // XXX_STINSON_CHUI_REWORK  	lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl; @@ -805,14 +822,14 @@ void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string c  //------------------------------------------------------------------------  LLVOAvatar::~LLVOAvatar()  { -	if (!mFullyLoaded) -	{ +		if (!mFullyLoaded) +		{  		debugAvatarRezTime("AvatarRezLeftCloudNotification","left after ruth seconds as cloud"); -	} -	else -	{ +		} +		else +		{  		debugAvatarRezTime("AvatarRezLeftNotification","left sometime after declouding"); -	} +		}  	lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; @@ -876,7 +893,11 @@ void LLVOAvatar::markDead()  		mNameText = NULL;  		sNumVisibleChatBubbles--;  	} +#ifdef XXX_STINSON_CHUI_REWORK  	mVoiceVisualizer->markDead(); +#else // XXX_STINSON_CHUI_REWORK +	mVoiceVisualizer->setStopSpeaking(); +#endif // XXX_STINSON_CHUI_REWORK  	LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;  	LLViewerObject::markDead();  } @@ -1214,18 +1235,6 @@ void LLVOAvatar::initClass()  		llerrs << "Error parsing skeleton file: " << skeleton_path << llendl;  	} -	// Process XML data - -	// avatar_skeleton.xml -	if (sAvatarSkeletonInfo) -	{ //this can happen if a login attempt failed -		delete sAvatarSkeletonInfo; -	} -	sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; -	if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) -	{ -		llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; -	}  	// parse avatar_lad.xml  	if (sAvatarXmlInfo)  	{ //this can happen if a login attempt failed @@ -1274,7 +1283,7 @@ void LLVOAvatar::initClass()  void LLVOAvatar::cleanupClass()  {  	deleteAndClear(sAvatarXmlInfo); -	sSkeletonXMLTree.cleanup(); +	sSkeletonXMLTree = NULL;  	sXMLTree.cleanup();  } @@ -1420,7 +1429,9 @@ void LLVOAvatar::initInstance(void)  	//VTPause();  // VTune +#ifdef XXX_STINSON_CHUI_REWORK  	mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); +#endif // XXX_STINSON_CHUI_REWORK  } @@ -1744,33 +1755,39 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)  	//-------------------------------------------------------------------------  	// parse the file  	//------------------------------------------------------------------------- -	BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); -	if (!parsesuccess) +	LLXMLNodePtr skeleton_xml; +	BOOL parsesuccess = LLXMLNode::parseFile(filename, skeleton_xml, NULL); + +	if (!parsesuccess || skeleton_xml.isNull())  	{  		llerrs << "Can't parse skeleton file: " << filename << llendl;  		return FALSE;  	} -	// now sanity check xml file -	LLXmlTreeNode* root = sSkeletonXMLTree.getRoot(); -	if (!root)  +	// Process XML data +	if (sAvatarSkeletonInfo) +	{ //this can happen if a login attempt failed +		delete sAvatarSkeletonInfo; +	} +	sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; + +	LLXUIParser parser; +	parser.readXUI(skeleton_xml, *sAvatarSkeletonInfo, filename); +	if (!sAvatarSkeletonInfo->validateBlock())  	{ -		llerrs << "No root node found in avatar skeleton file: " << filename << llendl; -		return FALSE; +		llerrs << "Error parsing skeleton XML file: " << filename << llendl;  	} -	if( !root->hasName( "linden_skeleton" ) ) +	if( !skeleton_xml->hasName( "linden_skeleton" ) )  	{  		llerrs << "Invalid avatar skeleton file header: " << filename << llendl;  		return FALSE;  	} -	std::string version; -	static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); -	if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) +	if (sAvatarSkeletonInfo->version() != "1.0")  	{ -		llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl; +		llerrs << "Invalid avatar skeleton file version: " << sAvatarSkeletonInfo->version() << " in file: " << filename << llendl;  		return FALSE;  	} @@ -1779,14 +1796,13 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)  //-----------------------------------------------------------------------------  // setupBone() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) +//----------------------------------------------------------- +BOOL LLVOAvatar::setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num)  {  	LLMemType mt(LLMemType::MTYPE_AVATAR);  	LLViewerJoint* joint = NULL; - -	if (info->mIsJoint) +	if (info.bone.isChosen())  	{  		joint = (LLViewerJoint*)getCharacterJoint(joint_num);  		if (!joint) @@ -1794,7 +1810,23 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent  			llwarns << "Too many bones" << llendl;  			return FALSE;  		} -		joint->setName( info->mName ); +		joint->setName( info.bone().name ); +		joint->setPosition(info.bone().pos); +		joint->setRotation(mayaQ(info.bone().rot().mV[VX], info.bone().rot().mV[VY], info.bone().rot().mV[VZ], LLQuaternion::XYZ)); +		joint->setScale(info.bone().scale); +		joint->setSkinOffset( info.bone().pivot ); +		joint_num++; + +		for (LLInitParam::ParamIterator<LLVOAvatarChildJoint>::const_iterator child_it = info.bone().children.begin(), +				end_it = info.bone().children.end(); +			child_it != end_it; +			++child_it) +		{ +			if (!setupBone(*child_it, joint, volume_num, joint_num)) +			{ +				return FALSE; +			} +	}  	}  	else // collision volume  	{ @@ -1804,7 +1836,11 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent  			return FALSE;  		}  		joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]); -		joint->setName( info->mName ); +		joint->setName( info.collision_volume.name); +		joint->setPosition(info.collision_volume.pos); +		joint->setRotation(mayaQ(info.collision_volume.rot().mV[VX], info.collision_volume.rot().mV[VY], info.collision_volume.rot().mV[VZ], LLQuaternion::XYZ)); +		joint->setScale(info.collision_volume.scale); +		volume_num++;  	}  	// add to parent @@ -1813,34 +1849,8 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent  		parent->addChild( joint );  	} -	joint->setPosition(info->mPos); -	joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], -							 info->mRot.mV[VZ], LLQuaternion::XYZ)); -	joint->setScale(info->mScale); -  	joint->setDefaultFromCurrentXform(); -	if (info->mIsJoint) -	{ -		joint->setSkinOffset( info->mPivot ); -		joint_num++; -	} -	else // collision volume -	{ -		volume_num++; -	} - -	// setup children -	LLVOAvatarBoneInfo::child_list_t::const_iterator iter; -	for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) -	{ -		LLVOAvatarBoneInfo *child_info = *iter; -		if (!setupBone(child_info, joint, volume_num, joint_num)) -		{ -			return FALSE; -		} -	} -  	return TRUE;  } @@ -1854,36 +1864,32 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)  	//-------------------------------------------------------------------------  	// allocate joints  	//------------------------------------------------------------------------- -	if (!allocateCharacterJoints(info->mNumBones)) +	if (!allocateCharacterJoints(info->num_bones))  	{ -		llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl; +		llerrs << "Can't allocate " << info->num_bones() << " joints" << llendl;  		return FALSE;  	}  	//-------------------------------------------------------------------------  	// allocate volumes  	//------------------------------------------------------------------------- -	if (info->mNumCollisionVolumes) +	if (info->num_collision_volumes)  	{ -		if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) +		if (!allocateCollisionVolumes(info->num_collision_volumes))  		{ -			llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl; +			llerrs << "Can't allocate " << info->num_collision_volumes() << " collision volumes" << llendl;  			return FALSE;  		}  	}  	S32 current_joint_num = 0;  	S32 current_volume_num = 0; -	LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; -	for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) + +	if (!setupBone(info->skeleton_root, NULL, current_volume_num, current_joint_num))  	{ -		LLVOAvatarBoneInfo *info = *iter; -		if (!setupBone(info, NULL, current_volume_num, current_joint_num)) -		{  			llerrs << "Error parsing bone in skeleton file" << llendl;  			return FALSE;  		} -	}  	return TRUE;  } @@ -2096,15 +2102,15 @@ void LLVOAvatar::releaseMeshData()  		LLFace* facep = mDrawable->getFace(0);  		if (facep)  		{ -			facep->setSize(0, 0); -			for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) -			{ -				facep = mDrawable->getFace(i); +		facep->setSize(0, 0); +		for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) +		{ +			facep = mDrawable->getFace(i);  				if (facep)  				{ -					facep->setSize(0, 0); -				} -			} +			facep->setSize(0, 0); +		} +	}  		}  	} @@ -2353,11 +2359,11 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys,  	U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);  	// Print out arrival information once we have name of avatar. -	if (has_name && getNVPair("FirstName")) -	{ -		mDebugExistenceTimer.reset(); +		if (has_name && getNVPair("FirstName")) +		{ +			mDebugExistenceTimer.reset();  		debugAvatarRezTime("AvatarRezArrivedNotification","avatar arrived"); -	} +		}  	if(retval & LLViewerObject::INVALID_UPDATE)  	{ @@ -2423,7 +2429,7 @@ void LLVOAvatar::dumpAnimationState()  //------------------------------------------------------------------------  // idleUpdate()  //------------------------------------------------------------------------ -BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  {  	LLMemType mt(LLMemType::MTYPE_AVATAR);  	LLFastTimer t(FTM_AVATAR_UPDATE); @@ -2431,12 +2437,12 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  	if (isDead())  	{  		llinfos << "Warning!  Idle on dead avatar" << llendl; -		return TRUE; +		return;  	}	   	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)))  	{ -		return TRUE; +		return;  	}  	checkTextureLoading() ; @@ -2519,12 +2525,11 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  	idleUpdateNameTag( root_pos_last );  	idleUpdateRenderCost(); - -	return TRUE;  }  void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  { +#ifdef XXX_STINSON_CHUI_REWORK  	bool render_visualizer = voice_enabled;  	// Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled. @@ -2537,6 +2542,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  	}  	mVoiceVisualizer->setVoiceEnabled(render_visualizer); +#endif // XXX_STINSON_CHUI_REWORK  	if ( voice_enabled )  	{		 @@ -2612,6 +2618,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  			}  		} +#ifdef XXX_STINSON_CHUI_REWORK  		//--------------------------------------------------------------------------------------------  		// here we get the approximate head position and set as sound source for the voice symbol  		// (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing) @@ -2629,6 +2636,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  			tagPos[VZ] += ( mBodySize[VZ] + 0.125f );  			mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos );  		} +#endif // XXX_STINSON_CHUI_REWORK  	}//if ( voiceEnabled )  }		 @@ -2868,8 +2876,8 @@ void LLVOAvatar::idleUpdateLoadingEffect()  		{  			LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL;  			mFirstFullyVisible = FALSE; -			LLAppearanceMgr::instance().onFirstFullyVisible(); -		} +				LLAppearanceMgr::instance().onFirstFullyVisible(); +			}  		if (isFullyLoaded() && mFirstFullyVisible && !isSelf())  		{  			LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL; @@ -3017,43 +3025,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)  		return;  	} -	BOOL new_name = FALSE; -	if (visible_chat != mVisibleChat) -	{ -		mVisibleChat = visible_chat; -		new_name = TRUE; -	} -		 -	if (sRenderGroupTitles != mRenderGroupTitles) -	{ -		mRenderGroupTitles = sRenderGroupTitles; -		new_name = TRUE; -	} - -	// First Calculate Alpha -	// If alpha > 0, create mNameText if necessary, otherwise delete it -	F32 alpha = 0.f; -	if (mAppAngle > 5.f) -	{ -		const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; -		if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) +		BOOL new_name = FALSE; +		if (visible_chat != mVisibleChat)  		{ -			alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; +			mVisibleChat = visible_chat; +			new_name = TRUE;  		} -		else +		 +		if (sRenderGroupTitles != mRenderGroupTitles)  		{ -			// ...not fading, full alpha -			alpha = 1.f; +			mRenderGroupTitles = sRenderGroupTitles; +			new_name = TRUE;  		} -	} -	else if (mAppAngle > 2.f) -	{ -		// far away is faded out also -		alpha = (mAppAngle-2.f)/3.f; -	} + +		// First Calculate Alpha +		// If alpha > 0, create mNameText if necessary, otherwise delete it +			F32 alpha = 0.f; +			if (mAppAngle > 5.f) +			{ +				const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; +				if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) +				{ +					alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; +				} +				else +				{ +					// ...not fading, full alpha +					alpha = 1.f; +				} +			} +			else if (mAppAngle > 2.f) +			{ +				// far away is faded out also +				alpha = (mAppAngle-2.f)/3.f; +			}  	if (alpha <= 0.f) -	{ +			{  		if (mNameText)  		{  			mNameText->markDead(); @@ -3063,22 +3071,21 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)  		return;  	} -	if (!mNameText) -	{ +				if (!mNameText) +				{  		mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject( -													LLHUDObject::LL_HUD_NAME_TAG) ); +			LLHUDObject::LL_HUD_NAME_TAG) );  		//mNameText->setMass(10.f); -		mNameText->setSourceObject(this); +					mNameText->setSourceObject(this);  		mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); -		mNameText->setVisibleOffScreen(TRUE); -		mNameText->setMaxLines(11); -		mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); -		sNumVisibleChatBubbles++; -		new_name = TRUE; -	} +					mNameText->setVisibleOffScreen(TRUE); +					mNameText->setMaxLines(11); +					mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); +					sNumVisibleChatBubbles++; +					new_name = TRUE; +				} -	LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); -	mNameText->setPositionAgent(name_position);				 +	idleUpdateNameTagPosition(root_pos_last);  	idleUpdateNameTagText(new_name);			  	idleUpdateNameTagAlpha(new_name, alpha);  } @@ -3166,7 +3173,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  			// trim last ", "  			line.resize( line.length() - 2 );  			addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, -						   LLFontGL::getFontSansSerifSmall()); +				LLFontGL::getFontSansSerifSmall());  		}  		if (sRenderGroupTitles @@ -3175,7 +3182,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  			std::string title_str = title->getString();  			LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR);  			addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, -						   LLFontGL::getFontSansSerifSmall()); +				LLFontGL::getFontSansSerifSmall());  		}  		static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); @@ -3189,14 +3196,14 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  				// ...call this function back when the name arrives  				// and force a rebuild  				LLAvatarNameCache::get(getID(), -									   boost::bind(&LLVOAvatar::clearNameTag, this)); +					boost::bind(&LLVOAvatar::clearNameTag, this));  			}  			// Might be blank if name not available yet, that's OK  			if (show_display_names)  			{  				addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, -							   LLFontGL::getFontSansSerif()); +					LLFontGL::getFontSansSerif());  			}  			// Suppress SLID display if display name matches exactly (ugh)  			if (show_usernames && !av_name.mIsDisplayNameDefault) @@ -3204,14 +3211,13 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  				// *HACK: Desaturate the color  				LLColor4 username_color = name_tag_color * 0.83f;  				addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, -							   LLFontGL::getFontSansSerifSmall()); +					LLFontGL::getFontSansSerifSmall());  			}  		}  		else  		{  			const LLFontGL* font = LLFontGL::getFontSansSerif(); -			std::string full_name = -				LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); +			std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() );  			addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font);  		} @@ -3231,7 +3237,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  		mNameText->setFont(LLFontGL::getFontSansSerif());  		mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT);  		mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); -			 +  		char line[MAX_STRING];		/* Flawfinder: ignore */  		line[0] = '\0';  		std::deque<LLChat>::iterator chat_iter = mChats.begin(); @@ -3251,13 +3257,13 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  			LLFontGL::StyleFlags style;  			switch(chat_iter->mChatType)  			{ -				case CHAT_TYPE_WHISPER: +			case CHAT_TYPE_WHISPER:  				style = LLFontGL::ITALIC;  				break; -				case CHAT_TYPE_SHOUT: +			case CHAT_TYPE_SHOUT:  				style = LLFontGL::BOLD;  				break; -				default: +			default:  				style = LLFontGL::NORMAL;  				break;  			} @@ -3284,13 +3290,13 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  			S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1;  			switch(dot_count)  			{ -				case 1: +			case 1:  				mNameText->addLine(".", new_chat);  				break; -				case 2: +			case 2:  				mNameText->addLine("..", new_chat);  				break; -				case 3: +			case 3:  				mNameText->addLine("...", new_chat);  				break;  			} @@ -3354,34 +3360,45 @@ void LLVOAvatar::invalidateNameTags()  		if (avatar->isDead()) continue;  		avatar->clearNameTag(); -  	}  }  // Compute name tag position during idle update -LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) +void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)  {  	LLQuaternion root_rot = mRoot.getWorldRotation(); +	LLQuaternion inv_root_rot = ~root_rot;  	LLVector3 pixel_right_vec;  	LLVector3 pixel_up_vec;  	LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec);  	LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin();  	camera_to_av.normalize(); -	LLVector3 local_camera_at = camera_to_av * ~root_rot; +	LLVector3 local_camera_at = camera_to_av * inv_root_rot;  	LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis();  	local_camera_up.normalize(); -	local_camera_up = local_camera_up * ~root_rot; +	local_camera_up = local_camera_up * inv_root_rot; -	local_camera_up.scaleVec(mBodySize * 0.5f); -	local_camera_at.scaleVec(mBodySize * 0.5f); +	LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, +								mBodySize.mV[VY] * 0.4f, +								mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); -	LLVector3 name_position = mRoot.getWorldPosition(); -	name_position[VZ] -= mPelvisToFoot; -	name_position[VZ] += (mBodySize[VZ]* 0.55f); +	local_camera_up.scaleVec(avatar_ellipsoid); +	local_camera_at.scaleVec(avatar_ellipsoid); + +	LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot.getLastWorldPosition()) * inv_root_rot; + +	if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) +	{ +		mTargetRootToHeadOffset = head_offset; +	} +	 +	mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLCriticalDamp::getInterpolant(0.2f)); + +	LLVector3 name_position = mRoot.getLastWorldPosition() + (mCurRootToHeadOffset * root_rot);  	name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av));	 -	name_position += pixel_up_vec * 15.f; +	name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; -	return name_position; +	mNameText->setPositionAgent(name_position);				  }  void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha) @@ -3454,9 +3471,9 @@ bool LLVOAvatar::isVisuallyMuted() const  	static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");  	static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); -	return LLMuteList::getInstance()->isMuted(getID()) || -			(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || -			(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); +	return LLMuteList::getInstance()->isMuted(getID())  +			|| (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0)  +			|| (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f);  }  //------------------------------------------------------------------------ @@ -3497,8 +3514,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		}  	} -	LLVector3d root_pos_global; -  	if (!mIsBuilt)  	{  		return FALSE; @@ -3513,7 +3528,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		mTimeVisible.reset();  	} -	  	//--------------------------------------------------------------------  	// the rest should only be done occasionally for far away avatars  	//-------------------------------------------------------------------- @@ -3916,10 +3930,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		if ( playSound )  		{ -//			F32 gain = clamp_rescale( mSpeedAccum, -//							AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, -//							AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); -  			const F32 STEP_VOLUME = 0.1f;  			const LLUUID& step_sound_id = getStepSound(); @@ -4136,13 +4146,6 @@ void LLVOAvatar::updateVisibility()  		{  			releaseMeshData();  		} -		// this breaks off-screen chat bubbles -		//if (mNameText) -		//{ -		//	mNameText->markDead(); -		//	mNameText = NULL; -		//	sNumVisibleChatBubbles--; -		//}  	}  	mVisible = visible; @@ -4158,46 +4161,6 @@ bool LLVOAvatar::shouldAlphaMask()  } -U32 LLVOAvatar::renderSkinnedAttachments() -{ -	/*U32 num_indices = 0; -	 -	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX |  -							LLVertexBuffer::MAP_NORMAL |  -							LLVertexBuffer::MAP_TEXCOORD0 | -							LLVertexBuffer::MAP_COLOR | -							LLVertexBuffer::MAP_WEIGHT4; - -	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();  -		 iter != mAttachmentPoints.end(); -		 ++iter) -	{ -		LLViewerJointAttachment* attachment = iter->second; -		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); -			 attachment_iter != attachment->mAttachedObjects.end(); -			 ++attachment_iter) -		{ -			const LLViewerObject* attached_object = (*attachment_iter); -			if (attached_object && !attached_object->isHUDAttachment()) -			{ -				const LLDrawable* drawable = attached_object->mDrawable; -				if (drawable) -				{ -					for (S32 i = 0; i < drawable->getNumFaces(); ++i) -					{ -						LLFace* face = drawable->getFace(i); -						if (face->isState(LLFace::RIGGED)) -						{ -							 -				} -			} -		} -	} - -	return num_indices;*/ -	return 0; -} -  //-----------------------------------------------------------------------------  // renderSkinned()  //----------------------------------------------------------------------------- @@ -4218,11 +4181,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  	{	//LOD changed or new mesh created, allocate new vertex buffer if needed  		if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4)  		{ -			updateMeshData(); +		updateMeshData();  			mDirtyMesh = 0; -			mNeedsSkin = TRUE; -			mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); -		} +		mNeedsSkin = TRUE; +		mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); +	}  	}  	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -4251,13 +4214,13 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  			if (face)  			{  				LLVertexBuffer* vb = face->getVertexBuffer(); -				if (vb) -				{ -					vb->flush(); -				} +			if (vb) +			{ +				vb->flush();  			}  		}  	} +	}  	else  	{  		mNeedsSkin = FALSE; @@ -5900,7 +5863,6 @@ BOOL LLVOAvatar::updateJointLODs()  	F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor);  	F32 area_scale = 0.16f; -	{  		if (isSelf())  		{  			if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) @@ -5930,7 +5892,6 @@ BOOL LLVOAvatar::updateJointLODs()  			dirtyMesh(2);  			return TRUE;  		} -	}  	return FALSE;  } @@ -6219,14 +6180,9 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )  		if ( pVObj )  		{  			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); -			if ( pSkinData ) -			{ -				const int jointCnt = pSkinData->mJointNames.size(); -				bool fullRig = ( jointCnt>=20 ) ? true : false; -				if ( fullRig ) -				{ -					const int bindCnt = pSkinData->mAlternateBindMatrix.size();							 -					if ( bindCnt > 0 ) +			if (pSkinData  +				&& pSkinData->mJointNames.size() > 20				// full rig +				&& pSkinData->mAlternateBindMatrix.size() > 0)  					{  						LLVOAvatar::resetJointPositionsToDefault();  						//Need to handle the repositioning of the cam, updating rig data etc during outfit editing  @@ -6241,8 +6197,6 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )  				}  			}				  		} -	}	 -}  //-----------------------------------------------------------------------------  // detachObject()  //----------------------------------------------------------------------------- @@ -6391,11 +6345,7 @@ void LLVOAvatar::getOffObject()  		at_axis.mV[VZ] = 0.f;  		at_axis.normalize();  		gAgent.resetAxes(at_axis); - -		//reset orientation -//		mRoot.setRotation(avWorldRot);  		gAgentCamera.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f)); -  		gAgentCamera.setSitCamera(LLUUID::null);  	}  } @@ -6445,7 +6395,6 @@ LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const  	}  	else  	{ -//		return LLColor4( .5f, .5f, .5f, .5f );  		return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color  	}  } @@ -6610,8 +6559,8 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading)  	mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE); -	if (!mPreviousFullyLoaded && !loading && mFullyLoaded) -	{ +		if (!mPreviousFullyLoaded && !loading && mFullyLoaded) +		{  		debugAvatarRezTime("AvatarRezNotification","fully loaded");  	} @@ -7204,10 +7153,6 @@ LLBBox LLVOAvatar::getHUDBBox() const  	return bbox;  } -void LLVOAvatar::rebuildHUD() -{ -} -  //-----------------------------------------------------------------------------  // onFirstTEMessageReceived()  //----------------------------------------------------------------------------- @@ -7333,7 +7278,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )  			&& baked_index != BAKED_SKIRT)  		{  			setTEImage(mBakedTextureDatas[baked_index].mTextureIndex,  -				LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); +						LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex,  +																TRUE,  +																LLViewerTexture::BOOST_NONE,  +																LLViewerTexture::LOD_TEXTURE));  		}  	} @@ -7592,7 +7540,7 @@ void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTextu  	LLUUID *avatar_idp = (LLUUID *)userdata;  	LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); -	 +  	if (selfp)  	{  		LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << LL_ENDL; @@ -7643,13 +7591,6 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success,  // Called when baked texture is loaded and also when we start up with a baked texture  void LLVOAvatar::useBakedTexture( const LLUUID& id )  { - -	 -	/* if(id == head_baked->getID()) -		 mHeadBakedLoaded = TRUE; -		 mLastHeadBakedID = id; -		 mHeadMesh0.setTexture( head_baked ); -		 mHeadMesh1.setTexture( head_baked ); */  	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)  	{  		LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); @@ -7893,111 +7834,111 @@ LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo()  	std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer());  } -//----------------------------------------------------------------------------- -// LLVOAvatarBoneInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) -{ -	if (node->hasName("bone")) -	{ -		mIsJoint = TRUE; -		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); -		if (!node->getFastAttributeString(name_string, mName)) -		{ -			llwarns << "Bone without name" << llendl; -			return FALSE; -		} -	} -	else if (node->hasName("collision_volume")) -	{ -		mIsJoint = FALSE; -		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); -		if (!node->getFastAttributeString(name_string, mName)) -		{ -			mName = "Collision Volume"; -		} -	} -	else -	{ -		llwarns << "Invalid node " << node->getName() << llendl; -		return FALSE; -	} - -	static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); -	if (!node->getFastAttributeVector3(pos_string, mPos)) -	{ -		llwarns << "Bone without position" << llendl; -		return FALSE; -	} - -	static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); -	if (!node->getFastAttributeVector3(rot_string, mRot)) -	{ -		llwarns << "Bone without rotation" << llendl; -		return FALSE; -	} -	 -	static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); -	if (!node->getFastAttributeVector3(scale_string, mScale)) -	{ -		llwarns << "Bone without scale" << llendl; -		return FALSE; -	} - -	if (mIsJoint) -	{ -		static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); -		if (!node->getFastAttributeVector3(pivot_string, mPivot)) -		{ -			llwarns << "Bone without pivot" << llendl; -			return FALSE; -		} -	} - -	// parse children -	LLXmlTreeNode* child; -	for( child = node->getFirstChild(); child; child = node->getNextChild() ) -	{ -		LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; -		if (!child_info->parseXml(child)) -		{ -			delete child_info; -			return FALSE; -		} -		mChildList.push_back(child_info); -	} -	return TRUE; -} - -//----------------------------------------------------------------------------- -// LLVOAvatarSkeletonInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) -{ -	static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); -	if (!node->getFastAttributeS32(num_bones_string, mNumBones)) -	{ -		llwarns << "Couldn't find number of bones." << llendl; -		return FALSE; -	} - -	static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); -	node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); - -	LLXmlTreeNode* child; -	for( child = node->getFirstChild(); child; child = node->getNextChild() ) -	{ -		LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; -		if (!info->parseXml(child)) -		{ -			delete info; -			llwarns << "Error parsing bone in skeleton file" << llendl; -			return FALSE; -		} -		mBoneInfoList.push_back(info); -	} -	return TRUE; -} +////----------------------------------------------------------------------------- +//// LLVOAvatarBoneInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) +//{ +//	if (node->hasName("bone")) +//	{ +//		mIsJoint = TRUE; +//		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +//		if (!node->getFastAttributeString(name_string, mName)) +//		{ +//			llwarns << "Bone without name" << llendl; +//			return FALSE; +//		} +//	} +//	else if (node->hasName("collision_volume")) +//	{ +//		mIsJoint = FALSE; +//		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +//		if (!node->getFastAttributeString(name_string, mName)) +//		{ +//			mName = "Collision Volume"; +//		} +//	} +//	else +//	{ +//		llwarns << "Invalid node " << node->getName() << llendl; +//		return FALSE; +//	} +// +//	static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); +//	if (!node->getFastAttributeVector3(pos_string, mPos)) +//	{ +//		llwarns << "Bone without position" << llendl; +//		return FALSE; +//	} +// +//	static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); +//	if (!node->getFastAttributeVector3(rot_string, mRot)) +//	{ +//		llwarns << "Bone without rotation" << llendl; +//		return FALSE; +//	} +//	 +//	static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); +//	if (!node->getFastAttributeVector3(scale_string, mScale)) +//	{ +//		llwarns << "Bone without scale" << llendl; +//		return FALSE; +//	} +// +//	if (mIsJoint) +//	{ +//		static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); +//		if (!node->getFastAttributeVector3(pivot_string, mPivot)) +//		{ +//			llwarns << "Bone without pivot" << llendl; +//			return FALSE; +//		} +//	} +// +//	// parse children +//	LLXmlTreeNode* child; +//	for( child = node->getFirstChild(); child; child = node->getNextChild() ) +//	{ +//		LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; +//		if (!child_info->parseXml(child)) +//		{ +//			delete child_info; +//			return FALSE; +//		} +//		mChildList.push_back(child_info); +//	} +//	return TRUE; +//} +// +////----------------------------------------------------------------------------- +//// LLVOAvatarSkeletonInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) +//{ +//	static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); +//	if (!node->getFastAttributeS32(num_bones_string, mNumBones)) +//	{ +//		llwarns << "Couldn't find number of bones." << llendl; +//		return FALSE; +//	} +// +//	static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); +//	node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); +// +//	LLXmlTreeNode* child; +//	for( child = node->getFirstChild(); child; child = node->getNextChild() ) +//	{ +//		LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; +//		if (!info->parseXml(child)) +//		{ +//			delete info; +//			llwarns << "Error parsing bone in skeleton file" << llendl; +//			return FALSE; +//		} +//		mBoneInfoList.push_back(info); +//	} +//	return TRUE; +//}  //-----------------------------------------------------------------------------  // parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index f5692bb52f..e45069dbfe 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -67,8 +67,9 @@ class LLVoiceVisualizer;  class LLHUDNameTag;  class LLHUDEffectSpiral;  class LLTexGlobalColor; -class LLVOAvatarBoneInfo; -class LLVOAvatarSkeletonInfo; +struct LLVOAvatarBoneInfo; +struct LLVOAvatarChildJoint; +struct LLVOAvatarSkeletonInfo;  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // LLVOAvatar @@ -134,7 +135,7 @@ public:  													 U32 block_num,  													 const EObjectUpdateType update_type,  													 LLDataPacker *dp); -	virtual BOOL   	 	 	idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	virtual void   	 	 	idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	virtual BOOL   	 	 	updateLOD();  	BOOL  	 	 	 	 	updateJointLODs();  	void					updateLODRiggedAttachments( void ); @@ -243,7 +244,7 @@ public:  	void 			idleUpdateWindEffect();  	void 			idleUpdateNameTag(const LLVector3& root_pos_last);  	void			idleUpdateNameTagText(BOOL new_name); -	LLVector3		idleUpdateNameTagPosition(const LLVector3& root_pos_last); +	void			idleUpdateNameTagPosition(const LLVector3& root_pos_last);  	void			idleUpdateNameTagAlpha(BOOL new_name, F32 alpha);  	LLColor4		getNameTagColor(bool is_friend);  	void			clearNameTag(); @@ -363,6 +364,8 @@ public:  	F32					mLastPelvisToFoot;  	F32					mPelvisFixup;  	F32					mLastPelvisFixup; +	LLVector3			mCurRootToHeadOffset; +	LLVector3			mTargetRootToHeadOffset;  	LLVector3			mHeadOffset; // current head position  	LLViewerJoint		mRoot; @@ -375,7 +378,7 @@ protected:  	void				buildCharacter();  	virtual BOOL		loadAvatar(); -	BOOL				setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); +	BOOL				setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num);  	BOOL				buildSkeleton(const LLVOAvatarSkeletonInfo *info);  private:  	BOOL				mIsBuilt; // state of deferred character building @@ -419,7 +422,7 @@ public:  	//--------------------------------------------------------------------  private:  	static LLXmlTree 	sXMLTree; // avatar config file -	static LLXmlTree 	sSkeletonXMLTree; // avatar skeleton file +	static LLXMLNodePtr	sSkeletonXMLTree; // avatar skeleton file  /**                    Skeleton   **                                                                            ** @@ -437,7 +440,6 @@ public:  	U32 		renderRigid();  	U32 		renderSkinned(EAvatarRenderPass pass);  	F32			getLastSkinTime() { return mLastSkinTime; } -	U32			renderSkinnedAttachments();  	U32 		renderTransparent(BOOL first_pass);  	void 		renderCollisionVolumes();  	static void	deleteCachedImages(bool clearAll=true); @@ -786,7 +788,6 @@ public:  public:  	BOOL 				hasHUDAttachment() const;  	LLBBox 				getHUDBBox() const; -	void 				rebuildHUD();  	void 				resetHUDAttachments();  	BOOL				canAttachMoreObjects() const;  	BOOL				canAttachMoreObjects(U32 n) const; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 6d672acc32..07b9b78255 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -668,15 +668,13 @@ BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent)  }  // virtual -BOOL LLVOAvatarSelf::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOAvatarSelf::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  { -	if (!isAgentAvatarValid()) +	if (isAgentAvatarValid())  	{ -		return TRUE; +		LLVOAvatar::idleUpdate(agent, world, time); +		idleUpdateTractorBeam();  	} -	LLVOAvatar::idleUpdate(agent, world, time); -	idleUpdateTractorBeam(); -	return TRUE;  }  // virtual diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 2b273e616c..7bd0c0bf93 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -85,7 +85,7 @@ protected:  	//--------------------------------------------------------------------  public:  	/*virtual*/ void 		updateRegion(LLViewerRegion *regionp); -	/*virtual*/ BOOL   	 	idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	/*virtual*/ void   	 	idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	//--------------------------------------------------------------------  	// LLCharacter interface and related diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 5ad9ccc9af..566c33c0af 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -277,17 +277,17 @@ BOOL LLVOGrass::isActive() const  	return TRUE;  } -BOOL LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  {   	if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_GRASS)))  	{ -		return TRUE; +		return;  	}  	if (!mDrawable)  	{  		// So drones work. -		return TRUE; +		return;  	}  	if(LLVOTree::isTreeRenderingStopped()) //stop rendering grass @@ -297,14 +297,14 @@ BOOL LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  			mNumBlades = 0 ;  			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);  		} -		return TRUE ; +		return;  	}  	else if(!mNumBlades)//restart grass rendering  	{  		mNumBlades = GRASS_MAX_BLADES ;  		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); -		return TRUE ; +		return;  	}  	if (mPatch && (mLastPatchUpdateTime != mPatch->getLastUpdateTime())) @@ -312,7 +312,7 @@ BOOL LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);  	} -	return TRUE; +	return;  } diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index 00a59facf7..b9835b8802 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -73,7 +73,7 @@ public:  	void plantBlades();  	/*virtual*/ BOOL    isActive() const; // Whether this object needs to do an idleUpdate. -	BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	/*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,   										  S32 face = -1,                        // which face to check, -1 = ALL_SIDES diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp index 6da54435e3..97b7418b40 100644 --- a/indra/newview/llvoground.cpp +++ b/indra/newview/llvoground.cpp @@ -49,18 +49,8 @@ LLVOGround::~LLVOGround()  {  } -BOOL LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  { - 	if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_GROUND))) -	{ -		return TRUE; -	} -	 -	/*if (mDrawable) -	{ -		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); -	}*/ -	return TRUE;  } diff --git a/indra/newview/llvoground.h b/indra/newview/llvoground.h index 73b097327e..290579b4da 100644 --- a/indra/newview/llvoground.h +++ b/indra/newview/llvoground.h @@ -41,7 +41,7 @@ protected:  public:  	LLVOGround(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); -	/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	/*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	// Graphical stuff for objects - maybe broken out into render class  	// later? diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 47060720e7..d380a8672f 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -45,6 +45,7 @@  //29de489d-0491-fb00-7dab-f9e686d31e83 +#ifdef XXX_STINSON_CHUI_REWORK  //--------------------------------------------------------------------------------------  // sound symbol constants  //-------------------------------------------------------------------------------------- @@ -60,6 +61,7 @@ const F32	BASE_BRIGHTNESS		= 0.7f;		// gray level of the voice indicator when qu  const F32	DOT_SIZE			= 0.05f;	// size of the dot billboard texture  const F32	DOT_OPACITY			= 0.7f;		// how opaque the dot is  const F32	WAVE_MOTION_RATE	= 1.5f;		// scalar applied to consecutive waves as a function of speaking amplitude +#endif // XXX_STINSON_CHUI_REWORK  //--------------------------------------------------------------------------------------  // gesticulation constants @@ -67,22 +69,13 @@ const F32	WAVE_MOTION_RATE	= 1.5f;		// scalar applied to consecutive waves as a  const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE	= 0.2f;   const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE	= 1.0f; +#ifdef XXX_STINSON_CHUI_REWORK  //--------------------------------------------------------------------------------------  // other constants  //--------------------------------------------------------------------------------------  const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code.   const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL - - -//------------------------------------------------------------------ -// handles parameter updates -//------------------------------------------------------------------ -static bool handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) -{ -	// Note: Ignore the specific event value, we look up the ones we want -	LLVoiceVisualizer::setPreferences(); -	return true; -} +#endif // XXX_STINSON_CHUI_REWORK  //------------------------------------------------------------------  // Initialize the statics @@ -105,12 +98,28 @@ F32	 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f;  //-----------------------------------------------  // constructor  //----------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) -:LLHUDEffect( type ) +	: LLHUDEffect(type) +#else // XXX_STINSON_CHUI_REWORK +LLVoiceVisualizer::LLVoiceVisualizer() +	: LLRefCount(), +	mTimer(), +	mStartTime(0.0), +	mCurrentlySpeaking(false), +	mSpeakingAmplitude(0.0f), +	mMaxGesticulationAmplitude(DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE), +	mMinGesticulationAmplitude(DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE) +#endif // XXX_STINSON_CHUI_REWORK  { +#ifdef XXX_STINSON_CHUI_REWORK  	mCurrentTime					= mTimer.getTotalSeconds();  	mPreviousTime					= mCurrentTime;  	mStartTime						= mCurrentTime; +#else // XXX_STINSON_CHUI_REWORK +	mStartTime						= mTimer.getTotalSeconds(); +#endif // XXX_STINSON_CHUI_REWORK +#ifdef XXX_STINSON_CHUI_REWORK  	mVoiceSourceWorldPosition		= LLVector3( 0.0f, 0.0f, 0.0f );  	mSpeakingAmplitude				= 0.0f;  	mCurrentlySpeaking				= false; @@ -119,9 +128,11 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )  	mMaxGesticulationAmplitude		= DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE;  	mSoundSymbol.mActive			= true;  	mSoundSymbol.mPosition			= LLVector3( 0.0f, 0.0f, 0.0f ); +#endif // XXX_STINSON_CHUI_REWORK  	mTimer.reset(); +#ifdef XXX_STINSON_CHUI_REWORK  	const char* sound_level_img[] =   	{  		"voice_meter_dot.j2c", @@ -143,6 +154,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )  	}  	mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); +#endif // XXX_STINSON_CHUI_REWORK  	// The first instance loads the initial state from prefs.  	if (!sPrefsInitialized) @@ -150,18 +162,19 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )  		setPreferences();  		// Set up our listener to get updates on all prefs values we care about. -		gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));  		sPrefsInitialized = true;  	}  }//--------------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m )  { @@ -182,13 +195,16 @@ void LLVoiceVisualizer::setVoiceEnabled( bool v )  	mVoiceEnabled = v;  }//--------------------------------------------------- +#endif // XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  void LLVoiceVisualizer::setStartSpeaking()  {  	mStartTime				= mTimer.getTotalSeconds();  	mCurrentlySpeaking		= true; +#ifdef XXX_STINSON_CHUI_REWORK  	mSoundSymbol.mActive	= true; +#endif // XXX_STINSON_CHUI_REWORK  }//--------------------------------------------------- @@ -217,6 +233,15 @@ void LLVoiceVisualizer::setSpeakingAmplitude( F32 a )  }//--------------------------------------------------- +//------------------------------------------------------------------ +// handles parameter updates +//------------------------------------------------------------------ +bool LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) +{ +	// Note: Ignore the specific event value, we look up the ones we want +	LLVoiceVisualizer::setPreferences(); +	return true; +}  //---------------------------------------------------  void LLVoiceVisualizer::setPreferences( ) @@ -334,6 +359,7 @@ void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah )  }//--------------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  // this method is inherited from HUD Effect  //--------------------------------------------------- @@ -526,16 +552,13 @@ void LLVoiceVisualizer::render()  }//--------------------------------------------------- - - - -  //---------------------------------------------------  void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p )  {  	mVoiceSourceWorldPosition	= p;  }//--------------------------------------------------- +#endif // XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() @@ -566,6 +589,7 @@ LLVoiceVisualizer::~LLVoiceVisualizer()  }//---------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  // "packData" is inherited from HUDEffect  //--------------------------------------------------- @@ -616,10 +640,4 @@ void LLVoiceVisualizer::markDead()  	LLHUDEffect::markDead();  }//------------------------------------------------------------------ - - - - - - - +#endif // XXX_STINSON_CHUI_REWORK diff --git a/indra/newview/llvoicevisualizer.h b/indra/newview/llvoicevisualizer.h index e434c7f3f1..5da592c48e 100644 --- a/indra/newview/llvoicevisualizer.h +++ b/indra/newview/llvoicevisualizer.h @@ -42,7 +42,12 @@  #ifndef LL_VOICE_VISUALIZER_H  #define LL_VOICE_VISUALIZER_H +#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot +#ifdef XXX_STINSON_CHUI_REWORK  #include "llhudeffect.h" +#else // XXX_STINSON_CHUI_REWORK +#include "llpointer.h" +#endif // XXX_STINSON_CHUI_REWORK  //-----------------------------------------------------------------------------------------------  // The values of voice gesticulation represent energy levels for avatar animation, based on  @@ -60,34 +65,45 @@ enum VoiceGesticulationLevel  	NUM_VOICE_GESTICULATION_LEVELS  }; +#ifdef XXX_STINSON_CHUI_REWORK  const static int NUM_VOICE_SYMBOL_WAVES = 7; +#endif // XXX_STINSON_CHUI_REWORK  //----------------------------------------------------  // LLVoiceVisualizer class   //---------------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  class LLVoiceVisualizer : public LLHUDEffect +#else // XXX_STINSON_CHUI_REWORK +class LLVoiceVisualizer : public LLRefCount +#endif // XXX_STINSON_CHUI_REWORK  {  	//---------------------------------------------------  	// public methods   	//---------------------------------------------------  	public: -		LLVoiceVisualizer ( const U8 type );	//constructor +#ifdef XXX_STINSON_CHUI_REWORK +		LLVoiceVisualizer( const U8 type );	//constructor +#else // XXX_STINSON_CHUI_REWORK +		LLVoiceVisualizer();	//constructor +#endif // XXX_STINSON_CHUI_REWORK  		~LLVoiceVisualizer();					//destructor -		 -		friend class LLHUDObject; +#ifdef XXX_STINSON_CHUI_REWORK  		void					setVoiceSourceWorldPosition( const LLVector3 &p );		// this should be the position of the speaking avatar's head  		void					setMinGesticulationAmplitude( F32 );					// the lower range of meaningful amplitude for setting gesticulation level   		void					setMaxGesticulationAmplitude( F32 );					// the upper range of meaningful amplitude for setting gesticulation level  +#endif // XXX_STINSON_CHUI_REWORK  		void					setStartSpeaking();										// tell me when the av starts speaking +#ifdef XXX_STINSON_CHUI_REWORK  		void					setVoiceEnabled( bool );								// tell me whether or not the user is voice enabled +#endif // XXX_STINSON_CHUI_REWORK  		void					setSpeakingAmplitude( F32 );							// tell me how loud the av is speaking (ranges from 0 to 1)  		void					setStopSpeaking();										// tell me when the av stops speaking  		bool					getCurrentlySpeaking();									// the get for the above set  		VoiceGesticulationLevel	getCurrentGesticulationLevel();							// based on voice amplitude, I'll give you the current "energy level" of avatar speech -		static void				setPreferences( ); -		static void				lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats  		void					lipSyncOohAah( F32& ooh, F32& aah ); +#ifdef XXX_STINSON_CHUI_REWORK  		void					render();												// inherited from HUD Effect  		void 					packData(LLMessageSystem *mesgsys);						// inherited from HUD Effect  		void 					unpackData(LLMessageSystem *mesgsys, S32 blocknum);		// inherited from HUD Effect @@ -103,12 +119,17 @@ class LLVoiceVisualizer : public LLHUDEffect  		//----------------------------------------------------------------------------------------------  		void setMaxGesticulationAmplitude();   		void setMinGesticulationAmplitude();  +#endif // XXX_STINSON_CHUI_REWORK  	//---------------------------------------------------  	// private members   	//---------------------------------------------------  	private: -	 +		static bool				handleVoiceVisualizerPrefsChanged(const LLSD& newvalue); +		static void				setPreferences( ); +		static void				lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats + +#ifdef XXX_STINSON_CHUI_REWORK  		struct SoundSymbol  		{  			F32						mWaveExpansion			[ NUM_VOICE_SYMBOL_WAVES ]; @@ -119,15 +140,20 @@ class LLVoiceVisualizer : public LLHUDEffect  			bool					mActive;  			LLVector3				mPosition;  		}; +#endif // XXX_STINSON_CHUI_REWORK  		LLFrameTimer			mTimer;							// so I can ask the current time in seconds  		F64						mStartTime;						// time in seconds when speaking started +#ifdef XXX_STINSON_CHUI_REWORK  		F64						mCurrentTime;					// current time in seconds, captured every step  		F64						mPreviousTime;					// copy of "current time" from last frame  		SoundSymbol				mSoundSymbol;					// the sound symbol that appears over the avatar's head  		bool					mVoiceEnabled;					// if off, no rendering should happen +#endif // XXX_STINSON_CHUI_REWORK  		bool					mCurrentlySpeaking;				// is the user currently speaking? +#ifdef XXX_STINSON_CHUI_REWORK  		LLVector3				mVoiceSourceWorldPosition;		// give this to me every step - I need it to update the sound symbol +#endif // XXX_STINSON_CHUI_REWORK  		F32						mSpeakingAmplitude;				// this should be set as often as possible when the user is speaking  		F32						mMaxGesticulationAmplitude;		// this is the upper-limit of the envelope of detectable gesticulation leves  		F32						mMinGesticulationAmplitude;		// this is the lower-limit of the envelope of detectable gesticulation leves diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 820d1d73e1..f1bf4a6d75 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -3964,6 +3964,7 @@ void LLVivoxVoiceClient::messageEvent(  						session->mCallerID,  						session->mName.c_str(),  						message.c_str(), +						false,  						LLStringUtil::null,		// default arg  						IM_NOTHING_SPECIAL,		// default arg  						0,						// default arg diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 9cce68fff6..c19996617b 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -152,8 +152,8 @@ bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)  void LLVOPartGroup::freeVBSlot(S32 idx)  {  	llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); -	llassert(sVBSlotCursor > sVBSlotFree); -	llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); +	//llassert(sVBSlotCursor > sVBSlotFree); +	//llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT));  	if (sVBSlotCursor > sVBSlotFree)  	{ @@ -196,9 +196,8 @@ void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)  	mDrawable->setPositionGroup(pos);  } -BOOL LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  { -	return TRUE;  }  void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent) diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 43b2844f07..42c1252d01 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -63,7 +63,7 @@ public:  	LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);  	/*virtual*/ BOOL    isActive() const; // Whether this object needs to do an idleUpdate. -	BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	virtual F32 getBinRadius();  	virtual void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 312034022e..31358df85f 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -1052,9 +1052,8 @@ void LLVOSky::calcAtmospherics(void)  	mFadeColor.setAlpha(0);  } -BOOL LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  { -	return TRUE;  }  BOOL LLVOSky::updateSky() diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index 6e6898d80a..2a150eccb9 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -461,7 +461,7 @@ public:  	void cleanupGL();  	void restoreGL(); -	/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	/*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	BOOL updateSky();  	// Graphical stuff for objects - maybe broken out into render class diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 94a3111f4c..cb905d02da 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -80,9 +80,9 @@ public:  			glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL]));  		}  		if (data_mask & MAP_TEXCOORD3) -		{ //substitute tex coord 0 for tex coord 3 +		{ //substitute tex coord 1 for tex coord 3  			glClientActiveTextureARB(GL_TEXTURE3_ARB); -			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); +			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1]));  			glClientActiveTextureARB(GL_TEXTURE0_ARB);  		}  		if (data_mask & MAP_TEXCOORD2) diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 337ddfb24d..6687ce432f 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -339,11 +339,11 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys,  	return retval;  } -BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  {   	if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE)))  	{ -		return TRUE; +		return;  	}  	S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ; @@ -393,8 +393,6 @@ BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  	}  	mTrunkLOD = trunk_LOD; - -	return TRUE;  }  const F32 TREE_BLEND_MIN = 1.f; diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index 0554935539..52debc85ab 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -59,7 +59,7 @@ public:  											void **user_data,  											U32 block_num, const EObjectUpdateType update_type,  											LLDataPacker *dp); -	/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	/*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	// Graphical stuff for objects - maybe broken out into render class later?  	/*virtual*/ void render(LLAgent &agent); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a656179c8f..958282f1eb 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -329,7 +329,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  			{  				if (!mTextureAnimp)  				{ -					mTextureAnimp = new LLViewerTextureAnim(); +					mTextureAnimp = new LLViewerTextureAnim(this);  				}  				else  				{ @@ -431,7 +431,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  			{  				if (!mTextureAnimp)  				{ -					mTextureAnimp = new LLViewerTextureAnim(); +					mTextureAnimp = new LLViewerTextureAnim(this);  				}  				else  				{ @@ -499,183 +499,144 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  void LLVOVolume::animateTextures()  { -	F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; -	S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); -	 -	if (result) +	if (!mDead)  	{ -		if (!mTexAnimMode) -		{ -			mFaceMappingChanged = TRUE; -			gPipeline.markTextured(mDrawable); -		} -		mTexAnimMode = result | mTextureAnimp->mMode; -				 -		S32 start=0, end=mDrawable->getNumFaces()-1; -		if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) -		{ -			start = end = mTextureAnimp->mFace; -		} -		 -		for (S32 i = start; i <= end; i++) +		F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; +		S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); +	 +		if (result)  		{ -			LLFace* facep = mDrawable->getFace(i); -			if (!facep) continue; -			if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; - -			const LLTextureEntry* te = facep->getTextureEntry(); -			 -			if (!te) +			if (!mTexAnimMode)  			{ -				continue; +				mFaceMappingChanged = TRUE; +				gPipeline.markTextured(mDrawable);  			} -		 -			if (!(result & LLViewerTextureAnim::ROTATE)) +			mTexAnimMode = result | mTextureAnimp->mMode; +				 +			S32 start=0, end=mDrawable->getNumFaces()-1; +			if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end)  			{ -				te->getRotation(&rot); +				start = end = mTextureAnimp->mFace;  			} -			if (!(result & LLViewerTextureAnim::TRANSLATE)) -			{ -				te->getOffset(&off_s,&off_t); -			}			 -			if (!(result & LLViewerTextureAnim::SCALE)) +		 +			for (S32 i = start; i <= end; i++)  			{ -				te->getScale(&scale_s, &scale_t); -			} +				LLFace* facep = mDrawable->getFace(i); +				if (!facep) continue; +				if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; -			if (!facep->mTextureMatrix) -			{ -				facep->mTextureMatrix = new LLMatrix4(); -			} +				const LLTextureEntry* te = facep->getTextureEntry(); +			 +				if (!te) +				{ +					continue; +				} +		 +				if (!(result & LLViewerTextureAnim::ROTATE)) +				{ +					te->getRotation(&rot); +				} +				if (!(result & LLViewerTextureAnim::TRANSLATE)) +				{ +					te->getOffset(&off_s,&off_t); +				}			 +				if (!(result & LLViewerTextureAnim::SCALE)) +				{ +					te->getScale(&scale_s, &scale_t); +				} + +				if (!facep->mTextureMatrix) +				{ +					facep->mTextureMatrix = new LLMatrix4(); +				} -			LLMatrix4& tex_mat = *facep->mTextureMatrix; -			tex_mat.setIdentity(); -			LLVector3 trans ; +				LLMatrix4& tex_mat = *facep->mTextureMatrix; +				tex_mat.setIdentity(); +				LLVector3 trans ; -			if(facep->isAtlasInUse()) -			{ -				// -				//if use atlas for animated texture -				//apply the following transform to the animation matrix. -				// - -				F32 tcoord_xoffset = 0.f ; -				F32 tcoord_yoffset = 0.f ; -				F32 tcoord_xscale = 1.f ; -				F32 tcoord_yscale = 1.f ;			  				if(facep->isAtlasInUse())  				{ -					const LLVector2* tmp = facep->getTexCoordOffset() ; -					tcoord_xoffset = tmp->mV[0] ;  -					tcoord_yoffset = tmp->mV[1] ; +					// +					//if use atlas for animated texture +					//apply the following transform to the animation matrix. +					// + +					F32 tcoord_xoffset = 0.f ; +					F32 tcoord_yoffset = 0.f ; +					F32 tcoord_xscale = 1.f ; +					F32 tcoord_yscale = 1.f ;			 +					if(facep->isAtlasInUse()) +					{ +						const LLVector2* tmp = facep->getTexCoordOffset() ; +						tcoord_xoffset = tmp->mV[0] ;  +						tcoord_yoffset = tmp->mV[1] ; -					tmp = facep->getTexCoordScale() ; -					tcoord_xscale = tmp->mV[0] ;  -					tcoord_yscale = tmp->mV[1] ;	 -				} -				trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f)); +						tmp = facep->getTexCoordScale() ; +						tcoord_xscale = tmp->mV[0] ;  +						tcoord_yscale = tmp->mV[1] ;	 +					} +					trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f)); -				tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f)); -			} -			else	//non atlas -			{ -				trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));			 -				tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); -			} +					tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f)); +				} +				else	//non atlas +				{ +					trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));			 +					tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); +				} -			LLVector3 scale(scale_s, scale_t, 1.f);			 -			LLQuaternion quat; -			quat.setQuat(rot, 0, 0, -1.f); +				LLVector3 scale(scale_s, scale_t, 1.f);			 +				LLQuaternion quat; +				quat.setQuat(rot, 0, 0, -1.f); -			tex_mat.rotate(quat);				 +				tex_mat.rotate(quat);				 -			LLMatrix4 mat; -			mat.initAll(scale, LLQuaternion(), LLVector3()); -			tex_mat *= mat; +				LLMatrix4 mat; +				mat.initAll(scale, LLQuaternion(), LLVector3()); +				tex_mat *= mat; -			tex_mat.translate(trans); +				tex_mat.translate(trans); +			}  		} -	} -	else -	{ -		if (mTexAnimMode && mTextureAnimp->mRate == 0) +		else  		{ -			U8 start, count; - -			if (mTextureAnimp->mFace == -1) +			if (mTexAnimMode && mTextureAnimp->mRate == 0)  			{ -				start = 0; -				count = getNumTEs(); -			} -			else -			{ -				start = (U8) mTextureAnimp->mFace; -				count = 1; -			} +				U8 start, count; -			for (S32 i = start; i < start + count; i++) -			{ -				if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) +				if (mTextureAnimp->mFace == -1)  				{ -					setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT);				 +					start = 0; +					count = getNumTEs();  				} -				if (mTexAnimMode & LLViewerTextureAnim::SCALE) +				else  				{ -					setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT);	 +					start = (U8) mTextureAnimp->mFace; +					count = 1;  				} -				if (mTexAnimMode & LLViewerTextureAnim::ROTATE) + +				for (S32 i = start; i < start + count; i++)  				{ -					setTERotation(i, mTextureAnimp->mRot); +					if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) +					{ +						setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT);				 +					} +					if (mTexAnimMode & LLViewerTextureAnim::SCALE) +					{ +						setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT);	 +					} +					if (mTexAnimMode & LLViewerTextureAnim::ROTATE) +					{ +						setTERotation(i, mTextureAnimp->mRot); +					}  				} -			} - -			gPipeline.markTextured(mDrawable); -			mFaceMappingChanged = TRUE; -			mTexAnimMode = 0; -		} -	} -} -BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) -{ -	LLViewerObject::idleUpdate(agent, world, time); - -	//static LLFastTimer::DeclareTimer ftm("Volume Idle"); -	//LLFastTimer t(ftm); -	if (mDead || mDrawable.isNull()) -	{ -		return TRUE; -	} -	 -	/////////////////////// -	// -	// Do texture animation stuff -	// - -	if (mTextureAnimp && gAnimateTextures) -	{ -		animateTextures(); -	} - -	// Dispatch to implementation -	if (mVolumeImpl) -	{ -		mVolumeImpl->doIdleUpdate(agent, world, time); -	} - -	const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40; - -	if (mDrawable->isActive()) -	{ -		if (mDrawable->isRoot() &&  -			mDrawable->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES &&  -			(!mDrawable->getParent() || !mDrawable->getParent()->isActive())) -		{ -			mDrawable->makeStatic(); +				gPipeline.markTextured(mDrawable); +				mFaceMappingChanged = TRUE; +				mTexAnimMode = 0; +			}  		}  	} - -	return TRUE;  }  void LLVOVolume::updateTextures() @@ -698,7 +659,8 @@ void LLVOVolume::updateTextures()  			}  		} -	} + +    }  }  BOOL LLVOVolume::isVisible() const  @@ -916,8 +878,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  BOOL LLVOVolume::isActive() const  { -	return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()) ||  -		(mDrawable.notNull() && mDrawable->isActive()); +	return !mStatic;  }  BOOL LLVOVolume::setMaterial(const U8 material) diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 8cb69930be..0082f2e991 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -68,7 +68,7 @@ class LLVolumeInterface  public:  	virtual ~LLVolumeInterface() { }  	virtual LLVolumeInterfaceType getInterfaceType() const = 0; -	virtual void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) = 0; +	virtual void doIdleUpdate() = 0;  	virtual BOOL doUpdateGeometry(LLDrawable *drawable) = 0;  	virtual LLVector3 getPivotPosition() const = 0;  	virtual void onSetVolume(const LLVolumeParams &volume_params, const S32 detail) = 0; @@ -114,8 +114,7 @@ public:  				void	deleteFaces();  				void	animateTextures(); -	/*virtual*/ BOOL	idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); - +	  	            BOOL    isVisible() const ;  	/*virtual*/ BOOL	isActive() const;  	/*virtual*/ BOOL	isAttachment() const; diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 942eff6171..e8a1c3d1d6 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -100,17 +100,8 @@ void LLVOWater::updateTextures()  }  // Never gets called -BOOL LLVOWater::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void  LLVOWater::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  { - 	/*if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER))) -	{ -		return TRUE; -	} -	if (mDrawable)  -	{ -		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); -	}*/ -	return TRUE;  }  LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline) diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h index ed709dd840..cf9323ef2e 100644 --- a/indra/newview/llvowater.h +++ b/indra/newview/llvowater.h @@ -58,7 +58,7 @@ public:  	static void initClass();  	static void cleanupClass(); -	/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	/*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);  	/*virtual*/ BOOL        updateGeometry(LLDrawable *drawable);  	/*virtual*/ void		updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index afd902201b..a33f42cf84 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -92,9 +92,9 @@ void LLVOWLSky::initSunDirection(LLVector3 const & sun_direction,  {  } -BOOL LLVOWLSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOWLSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  { -	return TRUE; +	  }  BOOL LLVOWLSky::isActive(void) const diff --git a/indra/newview/llvowlsky.h b/indra/newview/llvowlsky.h index 825e13a203..729dced15e 100644 --- a/indra/newview/llvowlsky.h +++ b/indra/newview/llvowlsky.h @@ -53,7 +53,7 @@ public:  	void initSunDirection(LLVector3 const & sun_direction,  		LLVector3 const & sun_angular_velocity); -	/*virtual*/ BOOL		 idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); +	/*virtual*/ void		 idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);  	/*virtual*/ BOOL		 isActive(void) const;  	/*virtual*/ LLDrawable * createDrawable(LLPipeline *pipeline);  	/*virtual*/ BOOL		 updateGeometry(LLDrawable *drawable); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7140515e46..c7ebaf6fbe 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -449,6 +449,19 @@ LLPipeline::LLPipeline() :  	mLightFunc = 0;  } +void LLPipeline::connectRefreshCachedSettingsSafe(const std::string name) +{ +	LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl(name); +	if ( cntrl_ptr.isNull() ) +	{ +		llwarns << "Global setting name not found:" << name << llendl; +	} +	else +	{ +		cntrl_ptr->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); +	} +} +  void LLPipeline::init()  {  	LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT); @@ -533,88 +546,86 @@ void LLPipeline::init()  	//  	// Update all settings to trigger a cached settings refresh  	// - -	gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderUseFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderAvatarMaxVisible")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderDelayVBUpdate")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	 -	gSavedSettings.getControl("UseOcclusion")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	 -	gSavedSettings.getControl("VertexShaderEnable")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderAvatarVP")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("WindLightUseAtmosShaders")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderDeferredSunWash")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderFSAASamples")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderResolutionDivisor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderUIBuffer")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderDeferredSSAO")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowResolutionScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderLocalLights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderDelayCreation")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderAnimateRes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("FreezeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("DebugBeaconLineWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderHighlightBrightness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderHighlightColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderHighlightThickness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderSpotLightsInNondeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewAmbientColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewDiffuse0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewSpecular0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewDiffuse1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewSpecular1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewDiffuse2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewSpecular2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewDirection0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewDirection1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("PreviewDirection2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderGlowMinLuminance")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderGlowMaxExtractAlpha")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderGlowWarmthAmount")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderGlowLumWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderGlowWarmthWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderGlowResolutionPow")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderGlowIterations")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderGlowWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderGlowStrength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderDepthOfField")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("CameraFocusTransitionTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("CameraFNumber")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("CameraFocalLength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("CameraFieldOfView")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowNoise")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowBlurSize")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderSSAOScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderSSAOMaxScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderSSAOFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderSSAOEffect")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowOffsetError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowBiasError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderSpotShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderSpotShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderEdgeDepthCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderEdgeNormCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowGaussian")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowBlurDistFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderDeferredAtmospheric")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderReflectionDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderHighlightFadeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowOrthoClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowNearDist")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowSplitExponent")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowErrorCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("RenderShadowFOVCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("CameraOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("CameraMaxCoF")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); -	gSavedSettings.getControl("CameraDoFResScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); +	connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaDeferred"); +	connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaNonDeferred"); +	connectRefreshCachedSettingsSafe("RenderUseFarClip"); +	connectRefreshCachedSettingsSafe("RenderAvatarMaxVisible"); +	connectRefreshCachedSettingsSafe("RenderDelayVBUpdate"); +	connectRefreshCachedSettingsSafe("UseOcclusion"); +	connectRefreshCachedSettingsSafe("VertexShaderEnable"); +	connectRefreshCachedSettingsSafe("RenderAvatarVP"); +	connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); +	connectRefreshCachedSettingsSafe("RenderDeferred"); +	connectRefreshCachedSettingsSafe("RenderDeferredSunWash"); +	connectRefreshCachedSettingsSafe("RenderFSAASamples"); +	connectRefreshCachedSettingsSafe("RenderResolutionDivisor"); +	connectRefreshCachedSettingsSafe("RenderUIBuffer"); +	connectRefreshCachedSettingsSafe("RenderShadowDetail"); +	connectRefreshCachedSettingsSafe("RenderDeferredSSAO"); +	connectRefreshCachedSettingsSafe("RenderShadowResolutionScale"); +	connectRefreshCachedSettingsSafe("RenderLocalLights"); +	connectRefreshCachedSettingsSafe("RenderDelayCreation"); +	connectRefreshCachedSettingsSafe("RenderAnimateRes"); +	connectRefreshCachedSettingsSafe("FreezeTime"); +	connectRefreshCachedSettingsSafe("DebugBeaconLineWidth"); +	connectRefreshCachedSettingsSafe("RenderHighlightBrightness"); +	connectRefreshCachedSettingsSafe("RenderHighlightColor"); +	connectRefreshCachedSettingsSafe("RenderHighlightThickness"); +	connectRefreshCachedSettingsSafe("RenderSpotLightsInNondeferred"); +	connectRefreshCachedSettingsSafe("PreviewAmbientColor"); +	connectRefreshCachedSettingsSafe("PreviewDiffuse0"); +	connectRefreshCachedSettingsSafe("PreviewSpecular0"); +	connectRefreshCachedSettingsSafe("PreviewDiffuse1"); +	connectRefreshCachedSettingsSafe("PreviewSpecular1"); +	connectRefreshCachedSettingsSafe("PreviewDiffuse2"); +	connectRefreshCachedSettingsSafe("PreviewSpecular2"); +	connectRefreshCachedSettingsSafe("PreviewDirection0"); +	connectRefreshCachedSettingsSafe("PreviewDirection1"); +	connectRefreshCachedSettingsSafe("PreviewDirection2"); +	connectRefreshCachedSettingsSafe("RenderGlowMinLuminance"); +	connectRefreshCachedSettingsSafe("RenderGlowMaxExtractAlpha"); +	connectRefreshCachedSettingsSafe("RenderGlowWarmthAmount"); +	connectRefreshCachedSettingsSafe("RenderGlowLumWeights"); +	connectRefreshCachedSettingsSafe("RenderGlowWarmthWeights"); +	connectRefreshCachedSettingsSafe("RenderGlowResolutionPow"); +	connectRefreshCachedSettingsSafe("RenderGlowIterations"); +	connectRefreshCachedSettingsSafe("RenderGlowWidth"); +	connectRefreshCachedSettingsSafe("RenderGlowStrength"); +	connectRefreshCachedSettingsSafe("RenderDepthOfField"); +	connectRefreshCachedSettingsSafe("CameraFocusTransitionTime"); +	connectRefreshCachedSettingsSafe("CameraFNumber"); +	connectRefreshCachedSettingsSafe("CameraFocalLength"); +	connectRefreshCachedSettingsSafe("CameraFieldOfView"); +	connectRefreshCachedSettingsSafe("RenderShadowNoise"); +	connectRefreshCachedSettingsSafe("RenderShadowBlurSize"); +	connectRefreshCachedSettingsSafe("RenderSSAOScale"); +	connectRefreshCachedSettingsSafe("RenderSSAOMaxScale"); +	connectRefreshCachedSettingsSafe("RenderSSAOFactor"); +	connectRefreshCachedSettingsSafe("RenderSSAOEffect"); +	connectRefreshCachedSettingsSafe("RenderShadowOffsetError"); +	connectRefreshCachedSettingsSafe("RenderShadowBiasError"); +	connectRefreshCachedSettingsSafe("RenderShadowOffset"); +	connectRefreshCachedSettingsSafe("RenderShadowBias"); +	connectRefreshCachedSettingsSafe("RenderSpotShadowOffset"); +	connectRefreshCachedSettingsSafe("RenderSpotShadowBias"); +	connectRefreshCachedSettingsSafe("RenderEdgeDepthCutoff"); +	connectRefreshCachedSettingsSafe("RenderEdgeNormCutoff"); +	connectRefreshCachedSettingsSafe("RenderShadowGaussian"); +	connectRefreshCachedSettingsSafe("RenderShadowBlurDistFactor"); +	connectRefreshCachedSettingsSafe("RenderDeferredAtmospheric"); +	connectRefreshCachedSettingsSafe("RenderReflectionDetail"); +	connectRefreshCachedSettingsSafe("RenderHighlightFadeTime"); +	connectRefreshCachedSettingsSafe("RenderShadowClipPlanes"); +	connectRefreshCachedSettingsSafe("RenderShadowOrthoClipPlanes"); +	connectRefreshCachedSettingsSafe("RenderShadowNearDist"); +	connectRefreshCachedSettingsSafe("RenderFarClip"); +	connectRefreshCachedSettingsSafe("RenderShadowSplitExponent"); +	connectRefreshCachedSettingsSafe("RenderShadowErrorCutoff"); +	connectRefreshCachedSettingsSafe("RenderShadowFOVCutoff"); +	connectRefreshCachedSettingsSafe("CameraOffset"); +	connectRefreshCachedSettingsSafe("CameraMaxCoF"); +	connectRefreshCachedSettingsSafe("CameraDoFResScale"); +	connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit");  	gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));  } @@ -720,7 +731,7 @@ void LLPipeline::destroyGL()  	{  		glDeleteQueriesARB(1, &mMeshDirtyQueryObject);  		mMeshDirtyQueryObject = 0; -} +	}  }  static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); @@ -879,7 +890,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)  			U32 sun_shadow_map_width = ((U32(resX*scale)+1)&~1); // must be even to avoid a stripe in the horizontal shadow blur  			for (U32 i = 0; i < 4; i++)  			{ -				if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; +				if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false;  			}  		}  		else @@ -1848,6 +1859,10 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)  		drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);  		if (done)  		{ +			if (drawablep->isRoot()) +			{ +				drawablep->makeStatic(); +			}  			drawablep->clearState(LLDrawable::ON_MOVE_LIST);  			if (drawablep->isState(LLDrawable::ANIMATED_CHILD))  			{ //will likely not receive any future world matrix updates @@ -3472,7 +3487,7 @@ void LLPipeline::postSort(LLCamera& camera)  	rebuildPriorityGroups();  	llpushcallstacks ; - +	  	//build render map  	for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)  	{ @@ -3544,7 +3559,7 @@ void LLPipeline::postSort(LLCamera& camera)  			}  		}  	} -		 +	  	//flush particle VB  	LLVOPartGroup::sVB->flush(); @@ -5206,11 +5221,6 @@ void LLPipeline::rebuildPools()  		}  		max_count--;  	} - -	if (isAgentAvatarValid()) -	{ -		gAgentAvatarp->rebuildHUD(); -	}  }  void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) @@ -5698,7 +5708,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)  				// crazy cast so that we can overwrite the fade value  				// even though gcc enforces sets as const  				// (fade value doesn't affect sort so this is safe) -				Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin())))); +				Light* farthest_light = (const_cast<Light*>(&(*(mNearbyLights.rbegin()))));  				if (light->dist < farthest_light->dist)  				{  					if (farthest_light->fade >= 0.f) @@ -6723,13 +6733,13 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable)  		LLFace* facep = drawable->getFace(i);  		if (facep)  		{ -		facep->clearVertexBuffer(); +			facep->clearVertexBuffer(); +		}  	}  } -}  void LLPipeline::resetVertexBuffers() -{ +{	  	mResetVertexBuffers = true;  } @@ -6765,6 +6775,8 @@ void LLPipeline::doResetVertexBuffers()  	gSky.resetVertexBuffers(); +	LLVOPartGroup::destroyGL(); +  	if ( LLPathingLib::getInstance() )  	{  		LLPathingLib::getInstance()->cleanupVBOManager(); @@ -7099,15 +7111,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)  				}  				else  				{ -					LLViewerObject* obj = gAgentCamera.getFocusObject(); -					if (obj) -					{ //focus on alt-zoom target -						focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal()); -					} -					else -					{ //focus on your avatar -						focus_point = gAgent.getPositionAgent(); -					} +					//focus on alt-zoom target +					focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal());  				}  			} @@ -7608,7 +7613,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n  	for (U32 i = 0; i < 4; i++)  	{ -		channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE); +		channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE);  		stop_glerror();  		if (channel > -1)  		{ @@ -7618,8 +7623,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n  			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);  			stop_glerror(); -			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); -			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);  			stop_glerror();  		}  	} @@ -7699,13 +7704,13 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n  								matrix_nondiag, matrix_nondiag, matrix_diag};  	shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat); -	F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); -	F32 shadow_bias_error = 1.f + RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); +	//F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); +	F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2])/3000.f;  	shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());  	shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f); -	shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset*shadow_offset_error); -	shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias*shadow_bias_error); +	shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error); +	shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias+shadow_bias_error);  	shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset);  	shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias);	 @@ -7996,7 +8001,7 @@ void LLPipeline::renderDeferredLighting()  				}  				mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - +				  				LLGLDepthTest depth(GL_TRUE, GL_FALSE);  				for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)  				{ @@ -8042,7 +8047,7 @@ void LLPipeline::renderDeferredLighting()  					}  					sVisibleLightCount++; - +										  					if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||  						camera->getOrigin().mV[0] < c[0] - s - 0.2f ||  						camera->getOrigin().mV[1] > c[1] + s + 0.2f || @@ -8429,9 +8434,9 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)  	for (U32 i = 0; i < 4; i++)  	{ -		if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1) +		if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1)  		{ -			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);  		}  	} @@ -8848,6 +8853,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera  		gGL.setColorMask(false, false);  		LLFastTimer ftm(FTM_SHADOW_SIMPLE); +		  		gGL.getTexUnit(0)->disable();  		for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)  		{ diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 368be1c14d..0140e24d63 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -382,6 +382,7 @@ private:  	BOOL updateDrawableGeom(LLDrawable* drawable, BOOL priority);  	void assertInitializedDoError();  	bool assertInitialized() { const bool is_init = isInit(); if (!is_init) assertInitializedDoError(); return is_init; }; +	void connectRefreshCachedSettingsSafe(const std::string name);  	void hideDrawable( LLDrawable *pDrawable );  	void unhideDrawable( LLDrawable *pDrawable );  public: diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 9bf2922033..05230b8bd5 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -1,103 +1,103 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <colors> -  <!-- Named Colors --> -  <color -      name="EmphasisColor" -      value="0.38 0.694 0.573 1" /> -  <color -      name="EmphasisColor_13" -      value="0.38 0.694 0.573 0.13" /> -  <color -      name="EmphasisColor_35" -      value="0.38 0.694 0.573 0.35" /> -  <color -      name="White" -      value="1 1 1 1" /> -  <color -      name="White_05" -      value="1 1 1 0.05" /> -  <color -      name="White_10" -      value="1 1 1 0.1" /> -  <color -      name="White_25" -      value="1 1 1 0.25" /> -  <color -      name="White_50" -      value="1 1 1 0.5" /> -  <color -      name="LtGray" -      value="0.75 0.75 0.75 1" /> -  <color -      name="LtGray_35" -      value="0.75 0.75 0.75 0.35" /> -  <color -      name="LtGray_50" -      value="0.75 0.75 0.75 0.50" /> -  <color -      name="Gray" -      value="0.5 0.5 0.5 1" /> -  <color -      name="DkGray" -      value="0.125 0.125 0.125 1" /> -  <color -      name="DkGray_66" -      value="0.125 0.125 0.125 .66" /> -  <color -      name="DkGray2" -      value="0.169 0.169 0.169 1" /> -  <color -      name="MouseGray" -      value="0.191 0.191 0.191 1" /> -  <color -      name="Black" -      value="0 0 0 1" /> -  <colork -      name="Black_10" -      value="0 0 0 0.1" /> -  <color -      name="Black_25" -      value="0 0 0 0.25" /> -  <color -      name="Black_50" -      value="0 0 0 0.5" /> -  <color -      name="FrogGreen" -      value="0.26 0.345 0.263 1" /> -  <color -      name="Red" -      value="1 0 0 1" /> -  <color -      name="Blue" -      value="0 0 1 1" /> -  <color -      name="Yellow" -      value="1 1 0 1" /> -  <color -      name="Green" -      value="0 1 0 1" /> -  <color -      name="Transparent" -      value="0 0 0 0" /> -  <color -      name="Purple" -      value="1 0 1 1" /> -  <color -      name="Lime" -      value=".8 1 .73 1" /> -  <color -      name="LtYellow" -      value="1 1 .79 1" /> -  <color -      name="DrYellow" -      value="1 0.86 0 1" /> -  <color -      name="LtOrange" -      value="1 .85 .73 1" /> -  <color -      name="MdBlue" -      value=".07 .38 .51 1" /> +	<!-- Named Colors --> +	<color +	 name="EmphasisColor" +	 value="0.38 0.694 0.573 1" /> +	<color +	 name="EmphasisColor_13" +	 value="0.38 0.694 0.573 0.13" /> +	<color +	 name="EmphasisColor_35" +	 value="0.38 0.694 0.573 0.35" /> +	<color +	 name="White" +	 value="1 1 1 1" /> +	<color +	 name="White_05" +	 value="1 1 1 0.05" /> +	<color +	 name="White_10" +	 value="1 1 1 0.1" /> +	<color +	 name="White_25" +	 value="1 1 1 0.25" /> +	<color +	 name="White_50" +	 value="1 1 1 0.5" /> +	<color +	 name="LtGray" +	 value="0.75 0.75 0.75 1" /> +	<color +	 name="LtGray_35" +	 value="0.75 0.75 0.75 0.35" /> +	<color +	 name="LtGray_50" +	 value="0.75 0.75 0.75 0.50" /> +	<color +	 name="Gray" +	 value="0.5 0.5 0.5 1" /> +	<color +	 name="DkGray" +	 value="0.125 0.125 0.125 1" /> +	<color +	 name="DkGray_66" +	 value="0.125 0.125 0.125 .66" /> +	<color +	 name="DkGray2" +	 value="0.169 0.169 0.169 1" /> +	<color +	 name="MouseGray" +	 value="0.191 0.191 0.191 1" /> +	<color +	 name="Black" +	 value="0 0 0 1" /> +	<colork +	 name="Black_10" +	 value="0 0 0 0.1" /> +	<color +	 name="Black_25" +	 value="0 0 0 0.25" /> +	<color +	 name="Black_50" +	 value="0 0 0 0.5" /> +	<color +	name="FrogGreen" +	value="0.26 0.345 0.263 1" /> +	<color +	 name="Red" +	 value="1 0 0 1" /> +	<color +	 name="Blue" +	 value="0 0 1 1" /> +	<color +	 name="Yellow" +	 value="1 1 0 1" /> +	<color +	 name="Green" +	 value="0 1 0 1" /> +	<color +	 name="Transparent" +	 value="0 0 0 0" /> +	<color +	name="Purple" +	value="1 0 1 1" /> +	<color +	name="Lime" +	value=".8 1 .73 1" /> +	<color +	name="LtYellow" +	value="1 1 .79 1" /> +	<color +	name="DrYellow" +	value="1 0.86 0 1" /> +	<color +	name="LtOrange" +	value="1 .85 .73 1" /> +	<color +	name="MdBlue" +	value=".07 .38 .51 1" />    <color        name="LtRed"        value="1 0.2 0.2 1" /> @@ -115,527 +115,527 @@        value="0 0 1 0.8" />    <!-- This color name makes potentially unused colors show up bright purple. -       Leave this here until all Unused? are removed below, otherwise -       the viewer generates many warnings on startup. --> +  Leave this here until all Unused? are removed below, otherwise +  the viewer generates many warnings on startup. -->    <color -      name="Unused?" -      value=".831 1 0 1" /> +	 name="Unused?" +	 value=".831 1 0 1" />    <!-- UI Definitions --> -  <color -      name="AccordionHeaderTextColor" -      reference="LtGray" /> -  <color -      name="AgentChatColor" -      reference="White" /> -  <color -      name="AlertBoxColor" -      value="0.24 0.24 0.24 1" /> -  <color -      name="AlertCautionBoxColor" -      value="1 0.82 0.46 1" /> -  <color -      name="AlertCautionTextColor" -      reference="LtYellow" /> -  <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="BadgeImageColor" -      value="1.0 0.40 0.0 1.0" /> -  <color -      name="BadgeBorderColor" -      value="0.9 0.9 0.9 1.0" /> -  <color -      name="BadgeLabelColor" -      reference="White" /> -  <color -      name="ButtonBorderColor" -      reference="Unused?" /> -  <color -      name="ButtonCautionImageColor" -      reference="Unused?" /> -  <color -      name="ButtonColor" -      reference="Unused?" /> -  <color -      name="ButtonFlashBgColor" -      reference="Unused?" /> -  <color -      name="ButtonImageColor" -      reference="White" /> -  <color -      name="ButtonLabelColor" -      reference="LtGray" /> -  <color -      name="ButtonLabelDisabledColor" -      reference="White_25" /> -  <color -      name="ButtonLabelSelectedColor" -      reference="White" /> -  <color -      name="ButtonLabelSelectedDisabledColor" -      reference="White_25" /> -  <color -      name="ButtonSelectedBgColor" -      reference="Unused?" /> -  <color -      name="ButtonSelectedColor" -      reference="Unused?" /> -  <color -      name="ButtonUnselectedBgColor" -      reference="Unused?" /> -  <color -      name="ButtonUnselectedFgColor" -      reference="Unused?" /> -  <color -      name="ChatHistoryBgColor" -      reference="Transparent" /> -  <color -      name="ChatHistoryTextColor" -      reference="LtGray" /> -  <color -      name="ChicletFlashColor" -      value="0.114 0.65 0.1" /> -  <color -      name="ColorDropShadow" -      reference="Black_50" /> -  <color -      name="ColorPaletteEntry01" -      reference="Black" /> -  <color -      name="ColorPaletteEntry02" -      reference="Gray" /> -  <color -      name="ColorPaletteEntry03" -      value="0.5 0 0 1" /> -  <color -      name="ColorPaletteEntry04" -      value="0.5 0.5 0 1" /> -  <color -      name="ColorPaletteEntry05" -      value="0 0.5 0 1" /> -  <color -      name="ColorPaletteEntry06" -      value="0 0.5 0.5 1" /> -  <color -      name="ColorPaletteEntry07" -      value="0 0 0.5 1" /> -  <color -      name="ColorPaletteEntry08" -      value="0.5 0 0.5 1" /> -  <color -      name="ColorPaletteEntry09" -      value="0.5 0.5 0 1" /> -  <color -      name="ColorPaletteEntry10" -      value="0 0.25 0.25 1" /> -  <color -      name="ColorPaletteEntry11" -      value="0 0.5 1 1" /> -  <color -      name="ColorPaletteEntry12" -      value="0 0.25 0.5 1" /> -  <color -      name="ColorPaletteEntry13" -      value="0.5 0 1 1" /> -  <color -      name="ColorPaletteEntry14" -      value="0.5 0.25 0 1" /> -  <color -      name="ColorPaletteEntry15" -      reference="White" /> -  <color -      name="ColorPaletteEntry16" -      reference="LtYellow" /> -  <color -      name="ColorPaletteEntry17" -      reference="White" /> -  <color -      name="ColorPaletteEntry18" -      reference="LtGray" /> -  <color -      name="ColorPaletteEntry19" -      reference="Red" /> -  <color -      name="ColorPaletteEntry20" -      reference="Yellow" /> -  <color -      name="ColorPaletteEntry21" -      reference="Green" /> -  <color -      name="ColorPaletteEntry22" -      value="0 1 1 1" /> -  <color -      name="ColorPaletteEntry23" -      reference="Blue" /> -  <color -      name="ColorPaletteEntry24" -      reference="Purple" /> -  <color -      name="ColorPaletteEntry25" -      value="1 1 0.5 1" /> -  <color -      name="ColorPaletteEntry26" -      value="0 1 0.5 1" /> -  <color -      name="ColorPaletteEntry27" -      value="0.5 1 1 1" /> -  <color -      name="ColorPaletteEntry28" -      value="0.5 0.5 1 1" /> -  <color -      name="ColorPaletteEntry29" -      value="1 0 0.5 1" /> -  <color -      name="ColorPaletteEntry30" -      value="1 0.5 0 1" /> -  <color -      name="ColorPaletteEntry31" -      reference="White" /> -  <color -      name="ColorPaletteEntry32" -      reference="White" /> -  <color -      name="ComboListBgColor" -      reference="DkGray" /> -  <color -      name="ConsoleBackground" -      reference="Black" /> -  <color -      name="ContextSilhouetteColor" -      reference="EmphasisColor" /> -  <color -      name="DefaultHighlightDark" -      reference="White_10" /> -  <color -      name="DefaultHighlightLight" -      reference="White_25" /> -  <color -      name="DefaultShadowDark" -      reference="Black_50" /> -  <color -      name="DefaultShadowLight" -      reference="Black_50" /> -  <color -      name="EffectColor" -      reference="White" /> -  <color -      name="FilterBackgroundColor" -      reference="Black" /> -  <color -      name="FilterTextColor" -      value="0.38 0.69 0.57 1" /> -  <color -      name="FloaterButtonImageColor" -      reference="LtGray" /> -  <color -      name="FloaterDefaultBackgroundColor" -      reference="DkGray_66" /> -  <color -      name="FloaterFocusBackgroundColor" -      reference="DkGray2" /> -  <color -      name="FloaterFocusBorderColor" -      reference="Black_50" /> -  <color -      name="FloaterUnfocusBorderColor" -      reference="Black_50" /> -  <color -      name="FocusColor" -      reference="EmphasisColor" /> -  <color -      name="FolderViewLoadingMessageTextColor" -      value="0.3344 0.5456 0.5159 1" /> -  <color -      name="GridFocusPointColor" -      reference="White_50" /> -  <color -      name="GridlineBGColor" -      value="0.92 0.92 1 0.78" /> -  <color -      name="GridlineColor" -      reference="White" /> -  <color -      name="GridlineShadowColor" -      value="0 0 0 0.31" /> -  <color -      name="GroupNotifyBoxColor" -      value="0.3344 0.5456 0.5159 1" /> -  <color -      name="GroupNotifyTextColor" -      reference="White"/> -  <color -      name="GroupNotifyDimmedTextColor" -      reference="LtGray" /> -  <color -      name="GroupOverTierColor" -      value="0.43 0.06 0.06 1" /> -  <color -      name="HTMLLinkColor" -      reference="EmphasisColor" /> -  <color -      name="HealthTextColor" -      reference="White" /> -  <color -      name="HelpBgColor" -      reference="Unused?" /> -  <color -      name="HelpFgColor" -      reference="Unused?" /> -  <color -      name="HelpScrollHighlightColor" -      reference="Unused?" /> -  <color -      name="HelpScrollShadowColor" -      reference="Unused?" /> -  <color -      name="HelpScrollThumbColor" -      reference="Unused?" /> -  <color -      name="HelpScrollTrackColor" -      reference="Unused?" /> -  <color -      name="HighlightChildColor" -      reference="Yellow" /> -  <color -      name="HighlightInspectColor" -      value="1 0 1 1" /> -  <color -      name="HighlightParentColor" -      value="0.67 0.83 0.96 1" /> -  <color -      name="IMHistoryBgColor" -      reference="Unused?" /> -  <color -      name="IMHistoryTextColor" -      reference="Unused?" /> -  <color -      name="IconDisabledColor" -      reference="White_25" /> -  <color -      name="IconEnabledColor" -      reference="White" /> -  <color -      name="InventoryBackgroundColor" -      reference="DkGray2" /> -  <color -      name="InventoryFocusOutlineColor" -      reference="White_25" /> -  <color -      name="InventoryItemSuffixColor" -      reference="White_25" /> -  <color -      name="InventoryItemLibraryColor" -      reference="EmphasisColor" /> -  <color -      name="InventoryItemLinkColor" -      reference="LtGray_50" /> -  <color -      name="InventoryMouseOverColor" -      reference="LtGray_35" /> -  <color -      name="InventorySearchStatusColor" -      reference="EmphasisColor" /> -  <color -      name="LabelDisabledColor" -      reference="White_25" /> -  <color -      name="LabelSelectedColor" -      reference="White" /> -  <color -      name="LabelSelectedDisabledColor" -      reference="White_25" /> -  <color -      name="LabelTextColor" -      reference="LtGray" /> -  <color -      name="LoginProgressBarBgColor" -      reference="Unused?" /> -  <color -      name="LoginProgressBarFgColor" -      reference="Unused?" /> -  <color -      name="LoginProgressBoxBorderColor" -      value="0 0.12 0.24 0" /> -  <color -      name="LoginProgressBoxCenterColor" -      value="0 0 0 0.78" /> -  <color -      name="LoginProgressBoxShadowColor" -      value="0 0 0 0.78" /> -  <color -      name="LoginProgressBoxTextColor" -      reference="White" /> -  <color -      name="MapAvatarColor" -      reference="Green" /> -  <color -      name="MapAvatarFriendColor" -      reference="Yellow" /> -  <color -      name="MapAvatarSelfColor" -      value="0.53125 0 0.498047 1" /> -  <color -      name="MapFrustumColor" -      reference="White_10" /> -  <color -      name="MapFrustumRotatingColor" -      value="1 1 1 0.2" /> -  <color -      name="MapTrackColor" -      reference="Red" /> -  <color -      name="MapTrackDisabledColor" -      value="0.5 0 0 1" /> -  <color -      name="MenuBarBgColor" -      reference="DkGray" /> -  <color -      name="MenuBarGodBgColor" -      reference="FrogGreen" /> -  <color -      name="MenuDefaultBgColor" -      reference="DkGray2" /> -  <color -      name="MenuItemDisabledColor" -      reference="LtGray_50" /> -  <color -      name="MenuItemEnabledColor" -      reference="LtGray" /> -  <color -      name="MenuItemHighlightBgColor" -      reference="EmphasisColor_35" /> -  <color -      name="MenuItemHighlightFgColor" -      reference="White" /> -  <color -      name="MenuNonProductionBgColor" -      reference="Black" /> -  <color -      name="MenuNonProductionGodBgColor" -      value="0.263 0.325 0.345 1" /> -  <color -      name="MenuPopupBgColor" -      reference="DkGray2" /> -  <color -      name="ModelUploaderLabels" -      value="1 0.6 0 1" />	   -  <color -      name="MultiSliderDisabledThumbColor" -      reference="Black" /> -  <color -      name="MultiSliderThumbCenterColor" -      reference="White" /> -  <color -      name="MultiSliderThumbCenterSelectedColor" -      reference="Green" /> -  <color -      name="MultiSliderThumbOutlineColor" -      reference="Unused?" /> -  <color -      name="MultiSliderTrackColor" -      reference="LtGray" /> -  <color -      name="MultiSliderTriangleColor" -      reference="Yellow" /> +    <color +     name="AccordionHeaderTextColor" +     reference="LtGray" /> +    <color +     name="AgentChatColor" +     reference="White" /> +    <color +     name="AlertBoxColor" +     value="0.24 0.24 0.24 1" /> +    <color +     name="AlertCautionBoxColor" +     value="1 0.82 0.46 1" /> +    <color +     name="AlertCautionTextColor" +     reference="LtYellow" /> +    <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="BadgeImageColor" +     value="1.0 0.40 0.0 1.0" /> +    <color +     name="BadgeBorderColor" +     value="0.9 0.9 0.9 1.0" /> +    <color +     name="BadgeLabelColor" +     reference="White" /> +    <color +     name="ButtonBorderColor" +     reference="Unused?" /> +    <color +     name="ButtonCautionImageColor" +     reference="Unused?" /> +    <color +     name="ButtonColor" +     reference="Unused?" /> +    <color +     name="ButtonFlashBgColor" +     reference="Unused?" /> +    <color +     name="ButtonImageColor" +     reference="White" /> +    <color +     name="ButtonLabelColor" +     reference="LtGray" /> +    <color +     name="ButtonLabelDisabledColor" +     reference="White_25" /> +    <color +     name="ButtonLabelSelectedColor" +     reference="White" /> +    <color +     name="ButtonLabelSelectedDisabledColor" +     reference="White_25" /> +    <color +     name="ButtonSelectedBgColor" +     reference="Unused?" /> +    <color +     name="ButtonSelectedColor" +     reference="Unused?" /> +    <color +     name="ButtonUnselectedBgColor" +     reference="Unused?" /> +    <color +     name="ButtonUnselectedFgColor" +     reference="Unused?" /> +    <color +     name="ChatHistoryBgColor" +     reference="Transparent" /> +    <color +     name="ChatHistoryTextColor" +     reference="LtGray" /> +    <color +     name="ChicletFlashColor" +     value="0.114 0.65 0.1" /> +    <color +     name="ColorDropShadow" +     reference="Black_50" /> +    <color +     name="ColorPaletteEntry01" +     reference="Black" /> +    <color +     name="ColorPaletteEntry02" +     reference="Gray" /> +    <color +     name="ColorPaletteEntry03" +     value="0.5 0 0 1" /> +    <color +     name="ColorPaletteEntry04" +     value="0.5 0.5 0 1" /> +    <color +     name="ColorPaletteEntry05" +     value="0 0.5 0 1" /> +    <color +     name="ColorPaletteEntry06" +     value="0 0.5 0.5 1" /> +    <color +     name="ColorPaletteEntry07" +     value="0 0 0.5 1" /> +    <color +     name="ColorPaletteEntry08" +     value="0.5 0 0.5 1" /> +    <color +     name="ColorPaletteEntry09" +     value="0.5 0.5 0 1" /> +    <color +     name="ColorPaletteEntry10" +     value="0 0.25 0.25 1" /> +    <color +     name="ColorPaletteEntry11" +     value="0 0.5 1 1" /> +    <color +     name="ColorPaletteEntry12" +     value="0 0.25 0.5 1" /> +    <color +     name="ColorPaletteEntry13" +     value="0.5 0 1 1" /> +    <color +     name="ColorPaletteEntry14" +     value="0.5 0.25 0 1" /> +    <color +     name="ColorPaletteEntry15" +     reference="White" /> +    <color +     name="ColorPaletteEntry16" +     reference="LtYellow" /> +    <color +     name="ColorPaletteEntry17" +     reference="White" /> +    <color +     name="ColorPaletteEntry18" +     reference="LtGray" /> +    <color +     name="ColorPaletteEntry19" +     reference="Red" /> +    <color +     name="ColorPaletteEntry20" +     reference="Yellow" /> +    <color +     name="ColorPaletteEntry21" +     reference="Green" /> +    <color +     name="ColorPaletteEntry22" +     value="0 1 1 1" /> +    <color +     name="ColorPaletteEntry23" +     reference="Blue" /> +    <color +     name="ColorPaletteEntry24" +     reference="Purple" /> +    <color +     name="ColorPaletteEntry25" +     value="1 1 0.5 1" /> +    <color +     name="ColorPaletteEntry26" +     value="0 1 0.5 1" /> +    <color +     name="ColorPaletteEntry27" +     value="0.5 1 1 1" /> +    <color +     name="ColorPaletteEntry28" +     value="0.5 0.5 1 1" /> +    <color +     name="ColorPaletteEntry29" +     value="1 0 0.5 1" /> +    <color +     name="ColorPaletteEntry30" +     value="1 0.5 0 1" /> +    <color +     name="ColorPaletteEntry31" +     reference="White" /> +    <color +     name="ColorPaletteEntry32" +     reference="White" /> +    <color +     name="ComboListBgColor" +     reference="DkGray" /> +    <color +     name="ConsoleBackground" +     reference="Black" /> +    <color +     name="ContextSilhouetteColor" +     reference="EmphasisColor" /> +    <color +     name="DefaultHighlightDark" +     reference="White_10" /> +    <color +     name="DefaultHighlightLight" +     reference="White_25" /> +    <color +     name="DefaultShadowDark" +     reference="Black_50" /> +    <color +     name="DefaultShadowLight" +     reference="Black_50" /> +    <color +     name="EffectColor" +     reference="White" /> +     <color +     name="FilterBackgroundColor" +     reference="Black" /> +    <color +     name="FilterTextColor" +     value="0.38 0.69 0.57 1" /> +     <color +     name="FloaterButtonImageColor" +     reference="LtGray" /> +    <color +     name="FloaterDefaultBackgroundColor" +     reference="DkGray_66" /> +    <color +     name="FloaterFocusBackgroundColor" +     reference="DkGray2" /> +    <color +     name="FloaterFocusBorderColor" +     reference="Black_50" /> +    <color +     name="FloaterUnfocusBorderColor" +     reference="Black_50" /> +    <color +     name="FocusColor" +     reference="EmphasisColor" /> +    <color +     name="FolderViewLoadingMessageTextColor" +     value="0.3344 0.5456 0.5159 1" /> +    <color +     name="GridFocusPointColor" +     reference="White_50" /> +    <color +     name="GridlineBGColor" +     value="0.92 0.92 1 0.78" /> +    <color +     name="GridlineColor" +     reference="White" /> +    <color +     name="GridlineShadowColor" +     value="0 0 0 0.31" /> +    <color +     name="GroupNotifyBoxColor" +     value="0.3344 0.5456 0.5159 1" /> +    <color +     name="GroupNotifyTextColor" +     reference="White"/> +    <color +     name="GroupNotifyDimmedTextColor" +     reference="LtGray" /> +    <color +     name="GroupOverTierColor" +     value="0.43 0.06 0.06 1" /> +    <color +     name="HTMLLinkColor" +     reference="EmphasisColor" /> +    <color +     name="HealthTextColor" +     reference="White" /> +    <color +     name="HelpBgColor" +     reference="Unused?" /> +    <color +     name="HelpFgColor" +     reference="Unused?" /> +    <color +     name="HelpScrollHighlightColor" +     reference="Unused?" /> +    <color +     name="HelpScrollShadowColor" +     reference="Unused?" /> +    <color +     name="HelpScrollThumbColor" +     reference="Unused?" /> +    <color +     name="HelpScrollTrackColor" +     reference="Unused?" /> +    <color +     name="HighlightChildColor" +     reference="Yellow" /> +    <color +     name="HighlightInspectColor" +     value="1 0 1 1" /> +    <color +     name="HighlightParentColor" +     value="0.67 0.83 0.96 1" /> +    <color +     name="IMHistoryBgColor" +     reference="Unused?" /> +    <color +     name="IMHistoryTextColor" +     reference="Unused?" /> +    <color +     name="IconDisabledColor" +	 reference="White_25" /> +    <color +     name="IconEnabledColor" +     reference="White" /> +    <color +     name="InventoryBackgroundColor" +     reference="DkGray2" /> +    <color +     name="InventoryFocusOutlineColor" +     reference="White_25" /> +    <color +     name="InventoryItemSuffixColor" +     reference="White_25" /> +    <color +     name="InventoryItemLibraryColor" +     reference="EmphasisColor" /> +    <color +     name="InventoryItemLinkColor" +     reference="LtGray_50" /> +    <color +     name="InventoryMouseOverColor" +     reference="LtGray_35" /> +    <color +     name="InventorySearchStatusColor" +     reference="EmphasisColor" /> +    <color +     name="LabelDisabledColor" +     reference="White_25" /> +    <color +     name="LabelSelectedColor" +     reference="White" /> +    <color +     name="LabelSelectedDisabledColor" +     reference="White_25" /> +    <color +     name="LabelTextColor" +     reference="LtGray" /> +    <color +     name="LoginProgressBarBgColor" +     reference="Unused?" /> +    <color +     name="LoginProgressBarFgColor" +     reference="Unused?" /> +    <color +     name="LoginProgressBoxBorderColor" +     value="0 0.12 0.24 0" /> +    <color +     name="LoginProgressBoxCenterColor" +     value="0 0 0 0.78" /> +    <color +     name="LoginProgressBoxShadowColor" +     value="0 0 0 0.78" /> +    <color +     name="LoginProgressBoxTextColor" +     reference="White" /> +    <color +     name="MapAvatarColor" +     reference="Green" /> +    <color +     name="MapAvatarFriendColor" +     reference="Yellow" /> +    <color +     name="MapAvatarSelfColor" +     value="0.53125 0 0.498047 1" /> +    <color +     name="MapFrustumColor" +     reference="White_10" /> +    <color +     name="MapFrustumRotatingColor" +     value="1 1 1 0.2" /> +    <color +     name="MapTrackColor" +     reference="Red" /> +    <color +     name="MapTrackDisabledColor" +     value="0.5 0 0 1" /> +    <color +     name="MenuBarBgColor" +     reference="DkGray" /> +    <color +     name="MenuBarGodBgColor" +     reference="FrogGreen" /> +    <color +     name="MenuDefaultBgColor" +     reference="DkGray2" /> +    <color +     name="MenuItemDisabledColor" +	 reference="LtGray_50" /> +    <color +     name="MenuItemEnabledColor" +     reference="LtGray" /> +    <color +     name="MenuItemHighlightBgColor" +     reference="EmphasisColor_35" /> +    <color +     name="MenuItemHighlightFgColor" +     reference="White" /> +    <color +     name="MenuNonProductionBgColor" +     reference="Black" /> +    <color +     name="MenuNonProductionGodBgColor" +     value="0.263 0.325 0.345 1" /> +    <color +     name="MenuPopupBgColor" +	  reference="DkGray2" /> +    <color +     name="ModelUploaderLabels" +     value="1 0.6 0 1" />	   +    <color +     name="MultiSliderDisabledThumbColor" +     reference="Black" /> +    <color +     name="MultiSliderThumbCenterColor" +     reference="White" /> +    <color +     name="MultiSliderThumbCenterSelectedColor" +     reference="Green" /> +    <color +     name="MultiSliderThumbOutlineColor" +     reference="Unused?" /> +    <color +     name="MultiSliderTrackColor" +     reference="LtGray" /> +    <color +     name="MultiSliderTriangleColor" +     reference="Yellow" />    <!-- -      <color +    <color        name="NameTagBackground"        value="0.85 0.85 0.85 0.80" /> -  --> -  <color +      --> +    <color        name="NameTagBackground"        value="0 0 0 1" /> -  <color -      name="NameTagChat" -      reference="White" /> -  <color -      name="NameTagFriend" -      value="0.447 0.784 0.663 1" /> -  <color -      name="NameTagLegacy" -      reference="White" /> -  <color -      name="NameTagMatch" -      reference="White" /> -  <color -      name="NameTagMismatch" -      reference="White" /> -  <color -      name="NetMapBackgroundColor" -      value="0 0 0 1" /> -  <color -      name="NetMapGroupOwnAboveWater" -      reference="Purple" /> -  <color -      name="NetMapGroupOwnBelowWater" -      value="0.78 0 0.78 1" /> -  <color -      name="NetMapOtherOwnAboveWater" -      value="0.24 0.24 0.24 1" /> -  <color -      name="NetMapOtherOwnBelowWater" -      value="0.12 0.12 0.12 1" /> -  <color -      name="NetMapYouOwnAboveWater" -      value="0 1 1 1" /> -  <color -      name="NetMapYouOwnBelowWater" -      value="0 0.78 0.78 1" /> -  <color -      name="NotifyBoxColor" -      value="LtGray" /> -  <color -      name="NotifyCautionBoxColor" -      value="1 0.82 0.46 1" /> -  <color -      name="NotifyCautionWarnColor" -      reference="White" /> -  <color -      name="NotifyTextColor" -      reference="White" /> -  <color -      name="ObjectBubbleColor" -      reference="DkGray_66" /> -  <color -      name="ObjectChatColor" -      reference="EmphasisColor" /> -  <color -      name="OverdrivenColor" -      reference="Red" /> -  <color -      name="PanelDefaultBackgroundColor" -      reference="DkGray" /> -  <color -      name="PanelDefaultHighlightLight" -      reference="White_50" /> -  <color -      name="PanelFocusBackgroundColor" -      reference="DkGray2" /> -  <color -      name="PanelNotificationBackground" -      value="1 0.3 0.3 0" /> -  <color -      name="ParcelHoverColor" -      reference="White" /> -  <color +    <color +     name="NameTagChat" +     reference="White" /> +    <color +     name="NameTagFriend" +     value="0.447 0.784 0.663 1" /> +    <color +     name="NameTagLegacy" +     reference="White" /> +    <color +     name="NameTagMatch" +     reference="White" /> +    <color +     name="NameTagMismatch" +     reference="White" /> +    <color +     name="NetMapBackgroundColor" +     value="0 0 0 1" /> +    <color +     name="NetMapGroupOwnAboveWater" +     reference="Purple" /> +    <color +     name="NetMapGroupOwnBelowWater" +     value="0.78 0 0.78 1" /> +    <color +     name="NetMapOtherOwnAboveWater" +     value="0.24 0.24 0.24 1" /> +    <color +     name="NetMapOtherOwnBelowWater" +     value="0.12 0.12 0.12 1" /> +    <color +     name="NetMapYouOwnAboveWater" +     value="0 1 1 1" /> +    <color +     name="NetMapYouOwnBelowWater" +     value="0 0.78 0.78 1" /> +    <color +     name="NotifyBoxColor" +     value="LtGray" /> +    <color +     name="NotifyCautionBoxColor" +     value="1 0.82 0.46 1" /> +    <color +     name="NotifyCautionWarnColor" +     reference="White" /> +    <color +     name="NotifyTextColor" +     reference="White" /> +    <color +     name="ObjectBubbleColor" +     reference="DkGray_66" /> +    <color +     name="ObjectChatColor" +     reference="EmphasisColor" /> +    <color +     name="OverdrivenColor" +     reference="Red" /> +    <color +     name="PanelDefaultBackgroundColor" +     reference="DkGray" /> +    <color +     name="PanelDefaultHighlightLight" +     reference="White_50" /> +    <color +     name="PanelFocusBackgroundColor" +     reference="DkGray2" /> +    <color +     name="PanelNotificationBackground" +     value="1 0.3 0.3 0" /> +    <color +     name="ParcelHoverColor" +     reference="White" /> +    <color        name="PathfindingErrorColor"        reference="LtRed" />    <color @@ -657,205 +657,205 @@        name="PathfindingCharacterBeaconColor"        reference="Red_80" />    <color -      name="PieMenuBgColor" -      value="0.24 0.24 0.24 0.59" /> -  <color -      name="PieMenuLineColor" -      value="0 0 0 0.5" /> -  <color -      name="PieMenuSelectedColor" -      value="0.72 0.72 0.74 0.3" /> -  <color -      name="PropertyColorAuction" -      value="0.5 0 1 0.4" /> -  <color -      name="PropertyColorAvail" -      reference="Transparent" /> -  <color -      name="PropertyColorForSale" -      value="1 0.5 0 0.4" /> -  <color -      name="PropertyColorGroup" -      value="0 0.72 0.72 0.4" /> -  <color -      name="PropertyColorOther" -      value="1 0 0 0.4" /> -  <color -      name="PropertyColorSelf" -      value="0 1 0 0.4" /> -  <color -      name="ScriptBgReadOnlyColor" -      value="0.39 0.39 0.39 1" /> -  <color -      name="ScriptErrorColor" -      reference="Red" /> -  <color -      name="ScrollBGStripeColor" -      reference="Transparent" /> -  <color -      name="ScrollBgReadOnlyColor" +     name="PieMenuBgColor" +     value="0.24 0.24 0.24 0.59" /> +    <color +     name="PieMenuLineColor" +     value="0 0 0 0.5" /> +    <color +     name="PieMenuSelectedColor" +     value="0.72 0.72 0.74 0.3" /> +    <color +     name="PropertyColorAuction" +     value="0.5 0 1 0.4" /> +    <color +     name="PropertyColorAvail" +     reference="Transparent" /> +    <color +     name="PropertyColorForSale" +     value="1 0.5 0 0.4" /> +    <color +     name="PropertyColorGroup" +     value="0 0.72 0.72 0.4" /> +    <color +     name="PropertyColorOther" +     value="1 0 0 0.4" /> +    <color +     name="PropertyColorSelf" +     value="0 1 0 0.4" /> +    <color +     name="ScriptBgReadOnlyColor" +     value="0.39 0.39 0.39 1" /> +    <color +     name="ScriptErrorColor" +     reference="Red" /> +    <color +     name="ScrollBGStripeColor" +     reference="Transparent" /> +    <color +     name="ScrollBgReadOnlyColor"        reference="Transparent" /> -  <color -      name="ScrollBgWriteableColor" -      reference="White_05" /> -  <color -      name="ScrollDisabledColor" -      reference="White_25" /> -  <color -      name="ScrollHighlightedColor" -      reference="Unused?" /> -  <color -      name="ScrollHoveredColor" -      reference="EmphasisColor_13" /> -  <color -      name="ScrollSelectedBGColor" -      reference="EmphasisColor_35" /> -  <color -      name="ScrollSelectedFGColor" -      reference="White" /> -  <color -      name="ScrollUnselectedColor" -      reference="LtGray" /> -  <color -      name="ScrollbarThumbColor" -      reference="White" /> -  <color -      name="ScrollbarTrackColor" -      reference="Black" /> -  <color -      name="SelectedOutfitTextColor" -      reference="EmphasisColor" /> -  <color -      name="SilhouetteChildColor" -      value="0.13 0.42 0.77 1" /> -  <color -      name="SilhouetteParentColor" -      reference="Yellow" /> -  <color -      name="SliderDisabledThumbColor" -      reference="White_25" /> -  <color -      name="SliderThumbCenterColor" -      reference="White" /> -  <color -      name="SliderThumbOutlineColor" -      reference="White" /> -  <color -      name="SliderTrackColor" -      reference="Unused?" /> -  <color -      name="SpeakingColor" -      reference="FrogGreen" /> -  <color -      name="SystemChatColor" -      reference="LtGray" /> -  <color -      name="TextBgFocusColor" -      reference="White" /> -  <color -      name="TextBgReadOnlyColor" -      reference="White_05" /> -  <color -      name="TextBgWriteableColor" -      reference="LtGray" /> -  <color -      name="TextCursorColor" -      reference="Black" /> -  <color -      name="TextDefaultColor" -      reference="Black" /> -  <color -      name="TextEmbeddedItemColor" -      value="0 0 0.5 1" /> -  <color -      name="TextEmbeddedItemReadOnlyColor" -      reference="Unused?" /> -  <color -      name="TextFgColor" -      value="0.102 0.102 0.102 1" /> -  <color -      name="TextFgReadOnlyColor" -      reference="LtGray" /> -  <color -      name="TextFgTentativeColor" -      value="0.4 0.4 0.4 1" /> -  <color -      name="TimeTextColor" -      reference="LtGray" /> -  <color -      name="TitleBarFocusColor" -      reference="White_10" /> -  <color -      name="ToastBackground" -      value="0.3 0.3 0.3 0" /> -  <color -      name="ToolTipBgColor" -      value="0.937 0.89 0.655 1" /> -  <color -      name="ToolTipBorderColor" -      value="0.812 0.753 0.451 1" /> -  <color -      name="ToolTipTextColor" -      reference="DkGray2" /> -  <color -      name="InspectorTipTextColor" -      reference="LtGray" /> -  <color -      name="UserChatColor" -      reference="White" /> -  <color -      name="llOwnerSayChatColor" -      reference="LtYellow" /> +    <color +     name="ScrollBgWriteableColor" +     reference="White_05" /> +    <color +     name="ScrollDisabledColor" +     reference="White_25" /> +    <color +     name="ScrollHighlightedColor" +     reference="Unused?" /> +    <color +     name="ScrollHoveredColor" +     reference="EmphasisColor_13" /> +    <color +     name="ScrollSelectedBGColor" +     reference="EmphasisColor_35" /> +    <color +     name="ScrollSelectedFGColor" +     reference="White" /> +    <color +     name="ScrollUnselectedColor" +     reference="LtGray" /> +    <color +     name="ScrollbarThumbColor" +     reference="White" /> +    <color +     name="ScrollbarTrackColor" +     reference="Black" /> +    <color +     name="SelectedOutfitTextColor" +     reference="EmphasisColor" /> +    <color +     name="SilhouetteChildColor" +     value="0.13 0.42 0.77 1" /> +    <color +     name="SilhouetteParentColor" +     reference="Yellow" /> +    <color +     name="SliderDisabledThumbColor" +     reference="White_25" /> +    <color +     name="SliderThumbCenterColor" +     reference="White" /> +    <color +     name="SliderThumbOutlineColor" +     reference="White" /> +    <color +     name="SliderTrackColor" +     reference="Unused?" /> +    <color +     name="SpeakingColor" +     reference="FrogGreen" /> +    <color +     name="SystemChatColor" +     reference="LtGray" /> +    <color +     name="TextBgFocusColor" +     reference="White" /> +    <color +     name="TextBgReadOnlyColor" +	 reference="White_05" /> +    <color +     name="TextBgWriteableColor" +     reference="LtGray" /> +    <color +     name="TextCursorColor" +     reference="Black" /> +    <color +     name="TextDefaultColor" +     reference="Black" /> +    <color +     name="TextEmbeddedItemColor" +     value="0 0 0.5 1" /> +    <color +     name="TextEmbeddedItemReadOnlyColor" +     reference="Unused?" /> +    <color +     name="TextFgColor" +     value="0.102 0.102 0.102 1" /> +    <color +     name="TextFgReadOnlyColor" +     reference="LtGray" /> +    <color +     name="TextFgTentativeColor" +     value="0.4 0.4 0.4 1" /> +    <color +     name="TimeTextColor" +     reference="LtGray" /> +    <color +     name="TitleBarFocusColor" +     reference="White_10" /> +    <color +     name="ToastBackground" +     value="0.3 0.3 0.3 0" /> +    <color +     name="ToolTipBgColor" +     value="0.937 0.89 0.655 1" /> +    <color +     name="ToolTipBorderColor" +     value="0.812 0.753 0.451 1" /> +    <color +     name="ToolTipTextColor" +     reference="DkGray2" /> +    <color +     name="InspectorTipTextColor" +     reference="LtGray" /> +    <color +     name="UserChatColor" +     reference="Yellow" /> +    <color +     name="llOwnerSayChatColor" +     reference="LtYellow" /> -  <!-- New Colors --> -  <color -      name="OutputMonitorMutedColor" -      reference="DkGray2" /> -  <color -      name="SysWellItemUnselected" -      value="0 0 0 0" /> -  <color -      name="SysWellItemSelected" -      value="0.3 0.3 0.3 1.0" /> -  <color -      name="ColorSwatchBorderColor" -      value="0.45098 0.517647 0.607843 1"/> -  <color -      name="ChatTimestampColor" -      reference="White" /> -  <color -      name="MenuBarProjectBgColor" -      reference="MdBlue" /> +    <!-- New Colors --> +    <color +     name="OutputMonitorMutedColor" +     reference="DkGray2" /> +    <color +     name="SysWellItemUnselected" +     value="0 0 0 0" /> +    <color +     name="SysWellItemSelected" +     value="0.3 0.3 0.3 1.0" /> +    <color +    name="ColorSwatchBorderColor" +    value="0.45098 0.517647 0.607843 1"/> +    <color +     name="ChatTimestampColor" +     reference="White" /> +    <color +     name="MenuBarProjectBgColor" +     reference="MdBlue" /> -  <color +    <color        name="MeshImportTableNormalColor"        value="1 1 1 1"/> -  <color +    <color        name="MeshImportTableHighlightColor"        value="0.2 0.8 1 1"/> -  <color -      name="DirectChatColor" -      reference="LtOrange" /> +    <color +     name="DirectChatColor" +     reference="LtOrange" /> -  <color +    <color        name="ToolbarDropZoneColor"        value=".48 .69 1 .5" /> -  <!-- Generic color names (legacy) --> +    <!-- Generic color names (legacy) -->    <color -      name="white" -      value="1 1 1 1"/> +    name="white" +    value="1 1 1 1"/>    <color -      name="black" -      value="0 0 0 1"/> +    name="black" +    value="0 0 0 1"/>    <color -      name="red" -      value="1 0 0 1"/> +    name="red" +    value="1 0 0 1"/>    <color -      name="green" -      value="0 1 0 1"/> +    name="green" +    value="0 1 0 1"/>    <color -      name="blue" -      value="0 0 1 1"/> +    name="blue" +    value="0 0 1 1"/>  </colors> diff --git a/indra/newview/skins/default/textures/icons/Conv_log_inbox.png b/indra/newview/skins/default/textures/icons/Conv_log_inbox.png Binary files differnew file mode 100644 index 0000000000..bb6ca28147 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_log_inbox.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png Binary files differnew file mode 100755 index 0000000000..f024c733f3 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png Binary files differnew file mode 100755 index 0000000000..a19e720d42 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png Binary files differnew file mode 100755 index 0000000000..7f3f42639d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png Binary files differnew file mode 100755 index 0000000000..2880eb766a --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png Binary files differnew file mode 100755 index 0000000000..25a939d7f5 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png Binary files differnew file mode 100755 index 0000000000..82baabde47 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png Binary files differnew file mode 100755 index 0000000000..7d64abb042 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png Binary files differnew file mode 100755 index 0000000000..f0da962c2d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png Binary files differnew file mode 100755 index 0000000000..0db001dcdb --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png Binary files differnew file mode 100755 index 0000000000..0cf7edc2d4 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png Binary files differnew file mode 100755 index 0000000000..a0c15a6d3e --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 06f8f8c670..47b0c12fa0 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -162,7 +162,22 @@ with the same filename but different name    <texture name="ComboButton_On" file_name="widgets/ComboButton_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />    <texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />    <texture name="ComboButton_UpOff" file_name="widgets/ComboButton_UpOff.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> +    <texture name="Container" file_name="containers/Container.png" preload="false" /> + +  <texture name="Conv_toolbar_add_person" file_name="icons/Conv_toolbar_add_person.png" preload="false" /> +  <texture name="Conv_toolbar_arrow_ne" file_name="icons/Conv_toolbar_arrow_ne.png" preload="false" /> +  <texture name="Conv_toolbar_arrow_sw" file_name="icons/Conv_toolbar_arrow_sw.png" preload="false" /> +  <texture name="Conv_toolbar_call_log" file_name="icons/Conv_toolbar_call_log.png" preload="false" /> +  <texture name="Conv_toolbar_close" file_name="icons/Conv_toolbar_close.png" preload="false" /> +  <texture name="Conv_toolbar_collapse" file_name="icons/Conv_toolbar_collapse.png" preload="false" /> +  <texture name="Conv_toolbar_expand" file_name="icons/Conv_toolbar_expand.png" preload="false" /> +  <texture name="Conv_toolbar_hang_up" file_name="icons/Conv_toolbar_hang_up.png" preload="false" /> +  <texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" /> +  <texture name="Conv_toolbar_plus" file_name="icons/Conv_toolbar_plus.png" preload="false" /> +  <texture name="Conv_toolbar_sort" file_name="icons/Conv_toolbar_sort.png" preload="false" /> +  <texture name="Conv_log_inbox" file_name="icons/Conv_log_inbox.png" preload="false" /> +    <texture name="Copy" file_name="icons/Copy.png" preload="false" />    <texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml deleted file mode 100644 index 405557242f..0000000000 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ /dev/null @@ -1,85 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - positioning="specified" - left="10" - bottom="-10" - height="60" - layout="topleft" - legacy_header_height="25" - single_instance="true" - title="NEARBY CHAT" - save_rect="true" - save_visibility="true" - can_close="true" - can_minimize="true" - help_topic="chat_bar" - min_height="60" - min_width="150" - can_resize="true" - default_tab_group="1" - name="chat_bar" - width="300"> -    <panel -        top="20" -        class="panel_nearby_chat" -        follow="all" -        width="300" -        height="0" -        visible="false" -        filename="panel_nearby_chat.xml" -        name="nearby_chat" /> -    <panel width="300"  -           height="31"  -           left="0"  -           name="bottom_panel" -           bottom="-1"  -           follows="left|right|bottom"  -           tab_group="1"> -      <line_editor -        border_style="line" -        border_thickness="1" -        follows="left|right" -        height="23" -        label="Click here to chat." -        layout="topleft" -        left_delta="7" -        left="0" -        max_length_bytes="1023" -        name="chat_box" -        spellcheck="true" -        text_pad_left="5" -        text_pad_right="25" -        tool_tip="Press Enter to say, Ctrl+Enter to shout" -        top="2" -        width="255" /> -      <output_monitor -        auto_update="true" -        follows="right" -        draw_border="false" -        height="16" -        layout="topleft" -        left_pad="-24" -        mouse_opaque="true" -        name="chat_zone_indicator" -        top="6" -        visible="true" -        width="20" /> -      <button -        follows="right" -        is_toggle="true" -        width="20" -        top="2" -        layout="topleft" -        left_pad="12" -        image_disabled="ComboButton_UpOff" -        image_unselected="ComboButton_UpOff" -        image_selected="ComboButton_On" -        image_pressed="ComboButton_UpSelected" -        image_pressed_selected="ComboButton_Selected" -        height="23" -        chrome="true" -        name="show_nearby_chat" -        tool_tip="Shows/hides nearby chat log"> -      </button> -    </panel> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml new file mode 100644 index 0000000000..9cdeb0d788 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> + +<floater +  can_resize="true" +  positioning="cascading" +  height="400" +  min_height="100" +  min_width="390" +  layout="topleft" +  name="floater_conversation_log" +  save_rect="true" +  single_instance="true" +  reuse_instance="true" +  title="CONVERSATION LOG" +  width="450"> +	<panel +      follows="left|top|right" +      height="27" +      layout="topleft" +      left="0" +      name="buttons_panel" +      top="0"> +        <filter_editor +          follows="left|top|right" +          height="23" +          layout="topleft" +          left="8" +          label="Filter People" +          max_length_chars="300" +          name="people_filter_input" +          text_color="Black" +          text_pad_left="10" +          top="4" +          width="364" /> +        <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="Conv_toolbar_sort" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="5" +          menu_filename="menu_conversation_log_view.xml" +          menu_position="bottomleft" +          name="conversation_view_btn" +          top="3" +          width="31" /> +        <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="OptionsMenu_Off" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="2" +          name="conversations_gear_btn" +          top="3" +          width="31" /> +    </panel> +    <panel +      follows="all" +      height="370" +      layout="topleft" +      left="5" +      name="buttons_panel" +      right="-5" +      top_pad="5"> +    <conversation_log_list +      opaque="true" +      allow_select="true" +      follows="all" +      height="360" +      layout="topleft" +      left="3" +      keep_selection_visible_on_reshape="true" +      item_pad="2" +      multi_select="false" +      name="conversation_log_list" +      right="-3" +      top="5" /> +    </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml new file mode 100644 index 0000000000..27b744aefb --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="true" + default_tab_group="1" + height="361" + layout="topleft" + min_height="243" + min_width="234" + name="preview_conversation" + title="CONVERSATION:" + width="400"> +    <floater.string +     name="Title"> +        CONVERSATION: [NAME] +    </floater.string> +    <text +     type="string" +     length="1" +     follows="left|top" +     font="SansSerif" +     height="19" +     layout="topleft" +     left="10" +     name="desc txt" +     top="22" +     width="90"> +        Description: +    </text> +    <line_editor +     border_style="line" +     border_thickness="1" +     enabled="false" +     follows="left|top|right" +     font="SansSerif" +     height="22" +     layout="topleft" +     left_pad="0" +     max_length_bytes="127" +     name="description" +     width="296" /> +    <chat_history +     font="SansSerifSmall" +     follows="all" +     visible="true" +     height="310" +     name="chat_history" +     parse_highlights="true" +     parse_urls="true" +     left="5" +     width="390"> +    </chat_history> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e123de46c2..e439fc9005 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -1,49 +1,127 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <multi_floater - can_close="false"   + can_close="true"     can_minimize="true"   can_resize="true" - height="390" + height="430"   layout="topleft" + min_height="50"   name="floater_im_box"   help_topic="floater_im_box"   save_rect="true"   save_visibility="true"   single_instance="true"   title="CONVERSATIONS" - width="396"> -    <tab_container -     follows="left|right|top|bottom" -     height="390" + width="680"> +    <string +     name="collapse_icon" +     value="Conv_toolbar_collapse"/> +    <string +     name="expand_icon" +     value="Conv_toolbar_expand"/> +    <layout_stack +     animate="true"  +     follows="all" +     height="430"       layout="topleft" -     left="1" -     name="im_box_tab_container" -     tab_position="bottom" -     tab_width="64" -     tab_max_width = "134" -     tab_height="16" -     use_custom_icon_ctrl="true" -     tab_icon_ctrl_pad="2" -     halign="left" -     use_ellipses="true" +     left="0" +     name="conversations_stack" +     orientation="horizontal"       top="0" -     width="394"> -      <first_tab -       tab_bottom_image_flash="Toolbar_Left_Flash"/> -      <middle_tab -       tab_bottom_image_flash="Toolbar_Middle_Flash"/> -      <last_tab -       tab_bottom_image_flash="Toolbar_Right_Flash"/> -    </tab_container> -    <icon -     color="DefaultShadowLight" -     enabled="false" -     follows="left|right|bottom" -     height="17" -     image_name="tabarea.tga" -     layout="bottomleft" -     left="1" -     name="im_box_tab_container_icon" -     bottom="10" -     width="394" /> +     width="680"> +        <layout_panel +         auto_resize="true" +         user_resize="true"         +         height="430" +         name="conversations_layout_panel" +         min_dim="38" +         width="268" +         expanded_min_dim="120"> +            <layout_stack +             animate="false"  +             follows="left|top|right" +             height="35" +             layout="topleft" +             left="0" +             name="conversations_pane_buttons_stack" +             orientation="horizontal" +             top="0" +             width="268"> +                <layout_panel +                 auto_resize="true" +                 height="35" +                 name="conversations_pane_buttons_expanded"> +                    <menu_button +                     follows="top|left" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="Conv_toolbar_sort" +                     image_selected="Toolbar_Middle_Selected" +                     image_unselected="Toolbar_Middle_Off" +                     menu_filename="menu_participant_view.xml" +                     layout="topleft" +                     left="10" +                     name="sort_btn" +                     top="5" +                     width="31" /> +                    <button +                     follows="top|left" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="Conv_toolbar_plus" +                     image_selected="Toolbar_Middle_Selected" +                      image_unselected="Toolbar_Middle_Off" +                     layout="topleft" +                     top="5" +                     left_pad="4" +                     name="add_btn" +                     tool_tip="Add button on the left panel" +                     width="31"/> +                </layout_panel> +                <layout_panel +                 auto_resize="false" +                 height="35" +                 name="conversations_pane_buttons_collapsed" +                 width="41"> +                    <button +                     follows="right|top" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="Conv_toolbar_collapse" +                     image_selected="Toolbar_Middle_Selected" +                     image_unselected="Toolbar_Middle_Off" +                     layout="topleft" +                     top="5" +                     left="5" +                     name="expand_collapse_btn" +                     width="31" /> +                </layout_panel> +            </layout_stack> +            <panel +             follows="all" +             layout="topleft" +             name="conversations_list_panel" +             opaque="true" +             top_pad="0" +             left="5" +             height="390" +             width="263"/> +        </layout_panel> +        <layout_panel +         auto_resize="true" +         user_resize="true" +         height="430" +         name="messages_layout_panel" +         width="412" +         expanded_min_dim="205"> +            <panel_container +             follows="all" +             height="430" +             layout="topleft" +             left="0" +             name="im_box_tab_container" +             top="0" +             width="412"/> +        </layout_panel> +    </layout_stack>  </multi_floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 040b66623e..d6d48130ab 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <floater - legacy_header_height="18"   background_visible="true"   default_tab_group="1"   height="355" @@ -10,84 +9,256 @@   can_dock="false"   can_minimize="true"   can_close="true" + save_rect="true"   visible="false"   width="394"   can_resize="true" + can_tear_off="false"   min_width="250" - min_height="190"> + min_height="190" + positioning="relative"> +    <floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string> +    <floater.string name="call_btn_stop">Conv_toolbar_hang_up</floater.string> +    <floater.string +     name="collapse_icon" +     value="Conv_toolbar_collapse"/> +    <floater.string +     name="expand_icon" +     value="Conv_toolbar_expand"/> +    <floater.string +     name="tear_off_icon" +     value="Conv_toolbar_arrow_ne"/> +    <floater.string +     name="return_icon" +     value="Conv_toolbar_arrow_sw"/> +    <floater.string +     name="participant_added" +     value="[NAME] was invited to the conversation."/> +    <floater.string +     name="multiple_participants_added" +     value="[NAME] were invited to the conversation."/> +    <view +        follows="all" +        layout="topleft" +        name="contents_view" +        top="0" +        left="0" +        height="355" +        width="394">  +     <panel +         follows="left|top|right" +         layout="topleft" +         name="toolbar_panel" +         top="0" +         left="0" +         height="35" +         width="394">          +             <menu_button +                 menu_filename="menu_im_session_showmodes.xml" +                 follows="top|left" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_sort" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left="5" +                 name="view_options_btn" +                 top="5" +                 width="31" /> +             <button +                 enabled="false" +                 follows="top|left" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_add_person" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="4" +                 name="add_btn" +                 width="31"/> +             <button +                 follows="top|left" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_open_call" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="4" +                 name="voice_call_btn" +                 width="31"/> +             <button +                 follows="right|top" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_close" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left="283" +                 name="close_btn" +                 width="31" /> +             <button +                 follows="right|top" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_collapse" +                 image_selected="Toolbar_Middle_Selected" +             	 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="5" +                 name="expand_collapse_btn" +                 width="31" /> +             <button +                 follows="right|top" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_arrow_ne" +                 image_selected="Toolbar_Middle_Selected" +             	 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="5" +                 name="tear_off_btn" +                 width="31" /> +     </panel>    <layout_stack     animate="true"      default_tab_group="2"    follows="all" -  height="320" +  height="310"    width="394"    layout="topleft"    orientation="horizontal"    name="im_panels"    tab_group="1" -  top="20" +  top_pad="0"    left="0">      <layout_panel -      name="im_control_panel_holder" +      name="speakers_list_panel" +      follows="all"        min_width="115"        width="150"  -      height="320"  +      height="310"         auto_resize="false"> -      <panel -        name="panel_im_control_panel" +            <avatar_list +             color="DkGray2" +             follows="all" +             height="310" +             ignore_online_status="true"          layout="topleft" -        height="320" -        width="150"  -        follows="all"/> +             name="speakers_list" +             opaque="false" +             show_info_btn="true" +             show_profile_btn="false" +             show_speaking_indicator="false" +             width="150" />        </layout_panel>      <layout_panel         default_tab_group="3"         left="0"         tab_group="2" +       follows="all"         top="0" -       height="200" -	     width="244" -       user_resize="true"> -        <button -          height="20" -          follows="left|top" -          top="0" -          left="2" -          image_overlay="TabIcon_Open_Off" +       height="310" +	   width="244" +       layout="topleft" +       user_resize="true" +       auto_resize="true" +       visible="true" +       name="left_part_holder"> +        <panel +         name="trnsAndChat_panel" +         follows="all" +         layout="topleft" +         visible="true" +         height="275" +         width="244"> +         <layout_stack +          animate="true"  +          default_tab_group="2" +          follows="all" +          height="275" +          width="244"            layout="topleft" -          width="25" -          name="slide_left_btn" /> -         <button -          height="20" -          follows="left|top" +          visible="true" +          orientation="vertical" +          name="translate_and_chat_stack" +          tab_group="1" +          left_pad="0"            top="0" -          left="2" -          image_overlay="TabIcon_Close_Off" -          width="25" -          name="slide_right_btn" /> +          left="0"> +            <layout_panel +             auto_resize="false" +             height="26" +             layout="topleft" +             left_delta="0" +             name="translate_chat_checkbox_lp" +             top_delta="0" +             visible="true" +             width="230"> +                <check_box +                 top="10" +                 control_name="TranslateChat" +                 enabled="true" +                 height="16" +                 label="Translate chat" +                 layout="topleft" +                 left="5" +                 name="translate_chat_checkbox" +                 width="230" /> +            </layout_panel> +            <layout_panel +             height="248" +             width="230" +             layout="topleft" +             follows="all" +             left_delta="0" +             top_delta="0" +             bottom="0" +             visible="true" +             user_resize="true" +             auto_resize="true" +             name="chat_holder">                <chat_history  	 font="SansSerifSmall" -         follows="left|right|top|bottom" -         height="150" +             		follows="all" +             		visible="true" +             		height="240"           name="chat_history"           parse_highlights="true"           parse_urls="true" -        left="1" -         width="238"> +       	 width="230" +       	 left="0">          </chat_history> -        <line_editor -         bottom="0" -         left="3" -         follows="left|right|bottom" -	 font="SansSerifSmall" -         height="20" -         label="To" -         layout="bottomleft" -         name="chat_editor" -         spellcheck="true" -         tab_group="3" -         width="236"> -        </line_editor> +            </layout_panel> +           </layout_stack> +           </panel> +            <chat_editor +             bottom="0" +             expand_lines_count="5" +             follows="left|right|bottom" +	         font="SansSerifSmall" +             visible="true" +             height="20" +             is_expandable="true" +             label="To" +             layout="bottomleft" +             name="chat_editor" +             max_length="1023" +             spellcheck="true" +             tab_group="3" +             width="220" +             left="10" +             wrap="true"> +            </chat_editor>      </layout_panel>    </layout_stack> +    </view>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml index 08d0b00a83..8e143623ab 100644 --- a/indra/newview/skins/default/xui/en/floater_people.xml +++ b/indra/newview/skins/default/xui/en/floater_people.xml @@ -7,20 +7,20 @@    height="570"    help_topic="sidebar_people"    min_height="440" -  min_width="333" +  min_width="390"    layout="topleft"    name="floater_people"    save_rect="true"    single_instance="true"    reuse_instance="true"    title="PEOPLE" -  width="333"> +  width="390">      <panel_container        default_panel_name="panel_people"        follows="all"        height="570"        name="main_panel" -      width="333"> +      width="390">        <panel          class="panel_people"          name="panel_people" @@ -31,11 +31,5 @@          filename="panel_group_info_sidetray.xml"          label="Group Profile"          font="SansSerifBold"/> -      <panel -        class="panel_block_list_sidetray" -        name="panel_block_list_sidetray" -        filename="panel_block_list_sidetray.xml" -        label="Blocked Residents & Objects" -        font="SansSerifBold"/>      </panel_container>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_top_objects.xml b/indra/newview/skins/default/xui/en/floater_top_objects.xml index 4dfdcd15c7..0b71177345 100644 --- a/indra/newview/skins/default/xui/en/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/en/floater_top_objects.xml @@ -2,7 +2,7 @@  <floater   legacy_header_height="18"   can_resize="true" - height="350" + height="372"   layout="topleft"   min_height="300"   min_width="450" @@ -23,10 +23,6 @@          Time      </floater.string>      <floater.string -     name="scripts_mono_time_label"> -        Mono Time -    </floater.string> -    <floater.string       name="top_colliders_title">          Top Colliders      </floater.string> @@ -68,31 +64,35 @@          <scroll_list.columns           label="Score"           name="score" -         width="55" /> +         width="45" />          <scroll_list.columns           label="Name"           name="name" -         width="140" /> +         width="130" />          <scroll_list.columns           label="Owner"           name="owner" -         width="105" /> +         width="100" />          <scroll_list.columns           label="Location"           name="location" -         width="130" /> +         width="120" /> +        <scroll_list.columns +         label="Parcel" +         name="parcel" +         width="120" />          <scroll_list.columns           label="Time"           name="time" -         width="150" /> -        <scroll_list.columns -         label="Mono Time" -         name="mono_time" -         width="100" /> +         width="130" />            <scroll_list.columns            	label="URLs"            	name="URLs" -          	width="100" /> +         width="40" /> +        <scroll_list.columns +         label="Memory (KB)" +         name="memory" +         width="40" />  		<scroll_list.commit_callback            function="TopObjects.CommitObjectsList" />      </scroll_list> @@ -193,6 +193,38 @@        <button.commit_callback            function="TopObjects.GetByOwnerName" />      </button> +    <text +     type="string" +     length="1" +     follows="left|bottom" +     height="20" +     layout="topleft" +     left="10" +     top_pad="5" +     name="parcel_name_text" +     width="107"> +        Parcel: +    </text> +    <line_editor +     follows="left|bottom|right" +     height="20" +     layout="topleft" +     left_pad="3" +     name="parcel_name_editor" +     top_delta="-3" +     width="568" /> +    <button +     follows="bottom|right" +     height="23" +     label="Filter" +     layout="topleft" +     left_pad="5" +     name="filter_parcel_btn" +     top_delta="0" +     width="100"> +      <button.commit_callback +          function="TopObjects.GetByParcelName" /> +    </button>      <button       follows="bottom|right"       height="22" diff --git a/indra/newview/skins/default/xui/en/floater_voice_volume.xml b/indra/newview/skins/default/xui/en/floater_voice_volume.xml new file mode 100644 index 0000000000..9346295d5b --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_voice_volume.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- +  Not can_close / no title to avoid window chrome +  Single instance - only have one at a time, recycle it each spawn +--> +<floater + legacy_header_height="25" + bevel_style="in" + bg_opaque_image="Inspector_Background" + can_close="false" + can_minimize="false" + height="90" + layout="topleft" + name="floater_voice_volume" + single_instance="true" + sound_flags="0" + title="VOICE VOLUME" + visible="true" + width="245"> +    <text +     follows="top|left|right" +     font="SansSerifSmall" +     height="21" +     left="10" +     name="avatar_name" +     parse_urls="false" +     top="35" +     text_color="White" +     translate="false" +     use_ellipses="true" +     value="TestString PleaseIgnore" +     width="225" /> +    <slider +     follows="top|left" +     height="23" +     increment="0.01" +     left="1" +     max_val="0.95" +     min_val="0.05" +     name="volume_slider" +     show_text="false" +     tool_tip="Voice volume" +     top_pad="0" +     value="0.5" +     width="200" /> +    <button +     follows="top|left" +     height="16" +     image_disabled="Audio_Off" +     image_disabled_selected="AudioMute_Off" +     image_hover_selected="AudioMute_Over" +     image_selected="AudioMute_Off" +     image_unselected="Audio_Off" +     is_toggle="true" +     left_pad="0" +     top_delta="4" +     name="mute_btn" +     width="16" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index bc3bcd331b..c3481e6d4c 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -9,7 +9,7 @@   bg_opaque_image="Inspector_Background"   can_close="false"   can_minimize="false" - height="164" + height="130"   layout="topleft"   name="inspect_avatar"   single_instance="true" @@ -94,32 +94,17 @@       use_ellipses="true"       width="220">This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot      </text> -    <slider -     follows="top|left" -     height="23" -     increment="0.01" -     left="1" -     max_val="0.95" -     min_val="0.05" -     name="volume_slider" -     show_text="false" -     tool_tip="Voice volume" -     top_pad="0" -     value="0.5" -     width="200" /> -    <button +    <text       follows="top|left"       height="16" -     image_disabled="Audio_Off" -     image_disabled_selected="AudioMute_Off" -     image_hover_selected="AudioMute_Over" -     image_selected="AudioMute_Off" -     image_unselected="Audio_Off" -     is_toggle="true" -     left_pad="0" -     top_delta="4" -     name="mute_btn" -     width="16" /> +     left="8" +     name="avatar_profile_link" +     font="SansSerifSmall" +     text_color="White" +     top_pad="5" +     translate="false" +     value="[[LINK] View full profile]" +     width="175" />      <avatar_icon       follows="top|left"       height="38" @@ -130,83 +115,4 @@       name="avatar_icon"       top="10"       width="38" /> -<!-- Overlapping buttons for default actions -    llinspectavatar.cpp makes visible the most likely default action  ---> -    <button -     follows="top|left" -     height="20" -     label="Add Friend" -     left="8" -     top="135" -     name="add_friend_btn" -     width="90" /> -    <button -     follows="top|left" -     height="20" -     label="IM" -     left_delta="0" -     top_delta="0" -     name="im_btn" -     width="80" -     commit_callback.function="InspectAvatar.IM"/> -	<button -     follows="top|left" -     height="20" -     label="Profile" -     layout="topleft" -     name="view_profile_btn" -     left_delta="96" -     top_delta="0" -     tab_stop="false" -     width="80" /> -      <!--  gear buttons here --> -  <menu_button -     follows="top|left" -     height="20" -     layout="topleft" -     image_overlay="OptionsMenu_Off" -     menu_filename="menu_inspect_avatar_gear.xml" -     name="gear_btn" -     right="-5" -     top_delta="0" -     width="35" /> -	<menu_button -     follows="top|left" -     height="20" -     image_overlay="OptionsMenu_Off" -     menu_filename="menu_inspect_self_gear.xml" -     name="gear_self_btn" -     right="-5" -     top_delta="0" -     width="35" /> -  <panel  -    follows="top|left"  -    top="164"  -    left="0"  -    height="60"  -    width="228"  -    visible="false" -    background_visible="true" -    name="moderator_panel" -    background_opaque="true"  -    bg_opaque_color="MouseGray"> -    <button -      name="disable_voice" -      label="Disable Voice" -      top="20" -      width="95" -      height="20" -      left="10" -      commit_callback.function="InspectAvatar.DisableVoice"/> -    <button -      name="enable_voice" -      label="Enable Voice" -      top="20" -      width="95" -      height="20" -      left="10" -      visible="false"  -      commit_callback.function="InspectAvatar.EnableVoice"/> -  </panel>  </floater> diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml new file mode 100644 index 0000000000..b8d0eef956 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Conversation Context Menu"> +    <menu_item_call +     label="IM..." +     layout="topleft" +     name="IM"> +        <on_click +         function="Calllog.Action" +         parameter="im" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_im" /> +    </menu_item_call> +    <menu_item_call +     label="Voice call..." +     layout="topleft" +     name="Call"> +        <on_click +         function="Calllog.Action" +         parameter="call" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_call" /> +    </menu_item_call> +    <menu_item_call +     label="Open chat history..." +     layout="topleft" +     name="Chat history"> +        <on_click +         function="Calllog.Action" +         parameter="chat_history" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_view_chat_history" /> +    </menu_item_call> +    <menu_item_call +     label="View Profile" +     layout="topleft" +     name="View Profile"> +        <on_click +         function="Calllog.Action" +         parameter="view_profile" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_view_profile" /> +    </menu_item_call> +    <menu_item_call +    label="Offer Teleport" +    name="teleport"> +      <on_click +       function="Calllog.Action" +       parameter="offer_teleport"/> +      <on_enable +      function="Calllog.Enable" +      parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_separator /> +    <menu_item_check +     label="Add friend/Remove friend" +     layout="topleft" +     name="Friend_add_remove"> +        <menu_item_check.on_click +         function="Calllog.Action" +         parameter="add_rem_friend" /> +        <menu_item_check.on_check +         function="Calllog.Check" +         parameter="is_friend" /> +        <menu_item_check.on_enable +         function="Calllog.Enable" +         parameter="add_rem_friend" /> +    </menu_item_check> +    <menu_item_call +     label="Invite to group..." +     layout="topleft" +     name="Invite"> +        <on_click +         function="Calllog.Action" +         parameter="invite_to_group"/> +        <on_enable +         function="Calllog.Enable" +         parameter="can_invite_to_group" /> +    </menu_item_call> +    <menu_item_separator /> +    <menu_item_call +     label="Map" +     layout="topleft" +     name="Map"> +        <on_click +         function="Calllog.Action" +         parameter="show_on_map" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_show_on_map" /> +    </menu_item_call> +    <menu_item_call +     label="Share" +     layout="topleft" +     name="Share"> +        <on_click +         function="Calllog.Action" +         parameter="share" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_share" /> +    </menu_item_call> +    <menu_item_call +     label="Pay" +     layout="topleft" +     name="Pay"> +        <on_click +         function="Calllog.Action" +         parameter="pay" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_pay" /> +    </menu_item_call> +    <menu_item_check +     label="Block/Unblock" +     layout="topleft" +     name="Block/Unblock"> +        <menu_item_check.on_click +         function="Calllog.Action" +         parameter="block"/> +        <menu_item_check.on_check +         function="Calllog.Check" +         parameter="is_blocked" /> +        <menu_item_check.on_enable +         function="Calllog.Enable" +         parameter="can_block" /> +    </menu_item_check> + +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml new file mode 100644 index 0000000000..4ab8cb4f7d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu +     name="menu_conversation_view" +     left="0" bottom="0" visible="false" +     mouse_opaque="false"> +  <menu_item_check +   label="Sort by name" +   name="sort_by_name"> +      <on_click +       function="CallLog.Action" +       parameter="sort_by_name"/> +      <on_check +       function="CallLog.Check" +       parameter="sort_by_name"/> +  </menu_item_check> +  <menu_item_check +   label="Sort by date" +   name="sort_by_date"> +      <on_click +       function="CallLog.Action" +       parameter="sort_by_date" /> +      <on_check +       function="CallLog.Check" +       parameter="sort_by_date" /> +  </menu_item_check> +  <menu_item_separator /> +  <menu_item_check +   label="Sort friends on top" +   name="sort_by_friends"> +      <on_click +       function="CallLog.Action" +       parameter="sort_friends_on_top" /> +      <on_check +       function="CallLog.Check" +       parameter="sort_friends_on_top" /> +  </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_group_plus.xml b/indra/newview/skins/default/xui/en/menu_group_plus.xml index fce7414d80..eca9e7f3c9 100644 --- a/indra/newview/skins/default/xui/en/menu_group_plus.xml +++ b/indra/newview/skins/default/xui/en/menu_group_plus.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu name="menu_group_plus" +<toggleable_menu name="menu_group_plus"       left="0" bottom="0" visible="false"       mouse_opaque="false">    <menu_item_call name="item_join" label="Join Group..."> @@ -8,4 +8,4 @@    <menu_item_call name="item_new" label="New Group...">      <menu_item_call.on_click function="People.Group.Plus.Action" userdata="new_group" />    </menu_item_call> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml new file mode 100644 index 0000000000..483f24afd0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_modes" + left="0" bottom="0" visible="false" + mouse_opaque="false"> +    <menu_item_check +       label="Compact view" +       name="compact_view"> +      <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="compact_view"/> +      <menu_item_check.on_check +         function="IMSession.Menu.CompactExpandedModes.CheckItem" +         parameter="compact_view"/> +    </menu_item_check> +    <menu_item_check +       label="Expanded view" +       name="expanded_view"> +      <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="expanded_view"/> +      <menu_item_check.on_check +         function="IMSession.Menu.CompactExpandedModes.CheckItem" +         parameter="expanded_view"/> +    </menu_item_check> +    <menu_item_separator layout="topleft" /> +    <menu_item_check name="IMShowTime" label="Show time"> +        <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="IMShowTime" /> +        <menu_item_check.on_check +         function="IMSession.Menu.ShowModes.CheckItem" +         parameter="IMShowTime" /> +        <menu_item_check.on_enable +         function="IMSession.Menu.ShowModes.Enable" +         parameter="IMShowTime" /> +    </menu_item_check> +    <menu_item_check name="IMShowNamesForP2PConv" label="Show names in one-to-one conversations"> +        <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="IMShowNamesForP2PConv" /> +        <menu_item_check.on_check +         function="IMSession.Menu.ShowModes.CheckItem" +         parameter="IMShowNamesForP2PConv" /> +        <menu_item_check.on_enable +         function="IMSession.Menu.ShowModes.Enable" +         parameter="IMShowNamesForP2PConv" /> +          +    </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml deleted file mode 100644 index 76b188220d..0000000000 --- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml +++ /dev/null @@ -1,143 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<toggleable_menu -         create_jump_keys="true" -         layout="topleft" -         mouse_opaque="false" -         visible="false" -         name="Gear Menu"> -  <menu_item_call -   label="View Profile" -   enabled="true"  -   name="view_profile"> -    <menu_item_call.on_click -     function="InspectAvatar.ViewProfile"/> -  </menu_item_call> -  <menu_item_call -   label="Add Friend" -   name="add_friend"> -    <menu_item_call.on_click -     function="InspectAvatar.AddFriend"/> -    <menu_item_call.on_enable -     function="InspectAvatar.Gear.Enable"/> -  </menu_item_call> -  <menu_item_call -   label="IM" -   name="im"> -    <menu_item_call.on_click -     function="InspectAvatar.IM"/> -  </menu_item_call> -  <menu_item_call -   label="Call" -   enabled="true" -   name="call"> -    <menu_item_call.on_click -     function="InspectAvatar.Call"/> -    <menu_item_call.on_enable -     function="InspectAvatar.Gear.EnableCall"/> -  </menu_item_call> -  <menu_item_call -   label="Teleport" -   name="teleport"> -    <menu_item_call.on_click -     function="InspectAvatar.Teleport"/> -    <menu_item_call.on_enable -     function="InspectAvatar.Gear.EnableTeleportOffer"/> -  </menu_item_call> -  <menu_item_call -   label="Invite to Group" -   name="invite_to_group"> -    <menu_item_call.on_click -     function="InspectAvatar.InviteToGroup"/> -  </menu_item_call> -  <menu_item_separator /> -  <menu_item_call -   label="Block" -   name="block"> -    <menu_item_call.on_click -     function="InspectAvatar.ToggleMute"/> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableMute" /> -  </menu_item_call> -  <menu_item_call -   label="Unblock" -   name="unblock"> -    <menu_item_call.on_click -     function="InspectAvatar.ToggleMute"/> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableUnmute" /> -  </menu_item_call> -  <menu_item_call -   label="Report" -   name="report"> -    <menu_item_call.on_click -     function="InspectAvatar.Report"/> -  </menu_item_call>   -  <menu_item_call -   label="Freeze" -   name="freeze"> -    <menu_item_call.on_click -     function="InspectAvatar.Freeze"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleFreeze"/> -  </menu_item_call> -  <menu_item_call -   label="Eject" -   name="eject"> -    <menu_item_call.on_click -     function="InspectAvatar.Eject"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleEject"/> -  </menu_item_call> -  <menu_item_call -   label="Kick" -   name="kick"> -    <menu_item_call.on_click -     function="InspectAvatar.Kick"/> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableGod"/> -  </menu_item_call> -  <menu_item_call -  label="CSR" -  name="csr"> -    <menu_item_call.on_click -     function="InspectAvatar.CSR" /> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableGod" /> -  </menu_item_call> -  <menu_item_call -   label="Debug Textures" -   name="debug"> -    <menu_item_call.on_click -     function="Avatar.Debug"/> -    <menu_item_call.on_visible -     function="IsGodCustomerService"/> -  </menu_item_call> -  <menu_item_call -   label="Find On Map" -   name="find_on_map"> -    <menu_item_call.on_click -     function="InspectAvatar.FindOnMap"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleFindOnMap"/> -  </menu_item_call> -  <menu_item_call -   label="Zoom In" -   name="zoom_in"> -    <menu_item_call.on_click -     function="InspectAvatar.ZoomIn"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleZoomIn"/> -  </menu_item_call>   -  <menu_item_call -   label="Pay" -   name="pay"> -    <menu_item_call.on_click -     function="InspectAvatar.Pay"/> -  </menu_item_call> -  <menu_item_call -   label="Share" -   name="share"> -    <menu_item_call.on_click -     function="InspectAvatar.Share"/> -  </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml deleted file mode 100644 index 5e7b16ed4a..0000000000 --- a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml +++ /dev/null @@ -1,252 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - layout="topleft" - name="Self Pie"> -  <menu_item_call -   label="Sit Down" -   layout="topleft" -   name="Sit Down Here"> -    <menu_item_call.on_click -     function="Self.SitDown" -     parameter="" /> -    <menu_item_call.on_enable -     function="Self.EnableSitDown" /> -  </menu_item_call> -  <menu_item_call -   label="Stand Up" -   layout="topleft" -   name="Stand Up"> -    <menu_item_call.on_click -     function="Self.StandUp" -     parameter="" /> -    <menu_item_call.on_enable -     function="Self.EnableStandUp" /> -  </menu_item_call> -  <context_menu -   label="Take Off" -   layout="topleft" -   name="Take Off >"> -    <context_menu -     label="Clothes" -     layout="topleft" -     name="Clothes >"> -      <menu_item_call -       enabled="false" -       label="Shirt" -       layout="topleft" -       name="Shirt"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="shirt" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="shirt" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Pants" -       layout="topleft" -       name="Pants"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="pants" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="pants" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Skirt" -       layout="topleft" -       name="Skirt"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="skirt" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="skirt" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Shoes" -       layout="topleft" -       name="Shoes"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="shoes" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="shoes" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Socks" -       layout="topleft" -       name="Socks"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="socks" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="socks" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Jacket" -       layout="topleft" -       name="Jacket"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="jacket" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="jacket" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Gloves" -       layout="topleft" -       name="Gloves"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="gloves" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="gloves" /> -      </menu_item_call> -      <menu_item_call -            enabled="false" -            label="Undershirt" -            layout="topleft" -            name="Self Undershirt"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="undershirt" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="undershirt" /> -      </menu_item_call> -      <menu_item_call -        enabled="false" -        label="Underpants" -        layout="topleft" -        name="Self Underpants"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="underpants" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="underpants" /> -      </menu_item_call> -      <menu_item_call -        enabled="false" -        label="Tattoo" -        layout="topleft" -        name="Self Tattoo"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="tattoo" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="tattoo" /> -      </menu_item_call> -      <menu_item_call -        enabled="false" -        label="Alpha" -        layout="topleft" -        name="Self Alpha"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="alpha" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="alpha" /> -      </menu_item_call> -      <menu_item_separator -       layout="topleft" /> -      <menu_item_call -       label="All Clothes" -       layout="topleft" -       name="All Clothes"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="all" /> -      </menu_item_call> -    </context_menu> -    <context_menu -     label="HUD" -     layout="topleft" -     name="Object Detach HUD" /> -    <context_menu -     label="Detach" -     layout="topleft" -     name="Object Detach" /> -    <menu_item_call -     label="Detach All" -     layout="topleft" -     name="Detach All"> -      <menu_item_call.on_click -       function="Self.RemoveAllAttachments" -       parameter="" /> -      <menu_item_call.on_enable -       function="Self.EnableRemoveAllAttachments" /> -    </menu_item_call> -  </context_menu> -  <menu_item_call -  label="Change Outfit" -  layout="topleft" -  name="Chenge Outfit"> -    <menu_item_call.on_click -     function="CustomizeAvatar" /> -    <menu_item_call.on_enable -     function="Edit.EnableCustomizeAvatar" /> -  </menu_item_call> -  <menu_item_call label="Edit My Outfit" -  layout="topleft" -  name="Edit Outfit"> -    <menu_item_call.on_click -     function="EditOutfit" /> -    <menu_item_call.on_enable -     function="Edit.EnableCustomizeAvatar" /> -  </menu_item_call> -  <menu_item_call label="Edit My Shape" -  layout="topleft" -  name="Edit My Shape"> -    <menu_item_call.on_click -     function="EditShape" /> -    <menu_item_call.on_enable -     function="Edit.EnableEditShape" /> -  </menu_item_call> -  <menu_item_call -    label="My Friends" -    layout="topleft" -    name="Friends..."> -    <menu_item_call.on_click -     function="SideTray.PanelPeopleTab" -     parameter="friends_panel" /> -  </menu_item_call> -  <menu_item_call -   label="My Groups" -   layout="topleft" -   name="Groups..."> -    <menu_item_call.on_click -     function="SideTray.PanelPeopleTab" -     parameter="groups_panel" /> -  </menu_item_call> -  <menu_item_call -    label="My Profile" -    layout="topleft" -    name="Profile..."> -    <menu_item_call.on_click -     function="ShowAgentProfile" -     parameter="agent" /> -  </menu_item_call> -  <menu_item_call -   label="Debug Textures" -       name="Debug..."> -    <menu_item_call.on_click -     function="Avatar.Debug" /> -    <menu_item_call.on_visible -     function="IsGodCustomerService"/> -  </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml new file mode 100644 index 0000000000..6401b0e3b7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="participant_manu_view"> +    <menu_item_check +         label="Open conversation log" +         name="Conversation" +         visible="true"> +        <menu_item_check.on_check +         function="Floater.Visible" +         parameter="conversation" /> +        <menu_item_check.on_click +         function="Floater.Toggle" +         parameter="conversation" /> +      </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml b/indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml new file mode 100644 index 0000000000..63295ea27b --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu  +     name="menu_blocked_gear" +     left="0" bottom="0" visible="false" +     mouse_opaque="false"> +  <menu_item_call +   label="Unblock" +   name="unblock"> +      <on_click +       function="Block.Action" +       parameter="unblock_item" /> +      <on_enable +       function="Block.Enable" +       parameter="unblock_item" />  +  </menu_item_call> +  <menu_item_call +   label="Profile..." +   name="profile"> +      <on_click +       function="Block.Action" +       parameter="profile_item"/> +      <on_enable +       function="Block.Enable" +       parameter="profile_item" /> +  </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml b/indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml new file mode 100644 index 0000000000..0c7155667e --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu  +     name="menu_blocked_plus" +     left="0" bottom="0" visible="false" +     mouse_opaque="false"> +  <menu_item_call +   label="Block Resident by name..." +   name="block_resident_by_name"> +      <on_click +       function="Block.Action" +       parameter="block_res_by_name"/> +  </menu_item_call> +  <menu_item_call +   label="Block object by name" +   name="block_object_by_name"> +      <on_click +       function="Block.Action" +       parameter="block_obj_by_name"/> +  </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_blocked_view.xml b/indra/newview/skins/default/xui/en/menu_people_blocked_view.xml new file mode 100644 index 0000000000..2efb70ee37 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_blocked_view.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu  +     name="menu_blocked_view" +     left="0" bottom="0" visible="false" +     mouse_opaque="false"> +  <menu_item_check +   label="Sort by name" +   name="sort_by_name"> +      <on_click +       function="Block.Action" +       parameter="sort_by_name"/> +      <on_check +       function="Block.Check" +       parameter="sort_by_name"/> +  </menu_item_check> +  <menu_item_check +   label="Sort by type" +   name="sort_by_type"> +      <on_click +       function="Block.Action" +       parameter="sort_by_type" /> +      <on_check +       function="Block.Check" +       parameter="sort_by_type" /> +  </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index b452f96e7a..eab7b8c085 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -40,8 +40,4 @@       function="CheckControl"       parameter="FriendsListShowPermissions" />    </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> -    <menu_item_call.on_click function="People.Friends.ViewSort.Action" parameter="panel_block_list_sidetray" /> -  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups.xml b/indra/newview/skins/default/xui/en/menu_people_groups.xml index 8f89d37dbb..1e0364b84e 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups.xml @@ -1,8 +1,18 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu name="menu_group_plus" +<toggleable_menu name="menu_group_plus"   left="0" bottom="0" visible="false"   mouse_opaque="false" opaque="true" color="MenuDefaultBgColor">    <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_call     label="View Info"     name="View Info">      <menu_item_call.on_click @@ -23,7 +33,7 @@       parameter="chat" />    </menu_item_call>    <menu_item_call -   label="Call" +   label="Voice call"     name="Call">      <menu_item_call.on_click       function="People.Groups.Action" @@ -34,17 +44,6 @@    </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 @@ -54,4 +53,4 @@       function="People.Groups.Enable"       parameter="leave" />    </menu_item_call> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml index c710fe3b9b..73f79f1e70 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml @@ -14,13 +14,4 @@         function="CheckControl"         parameter="GroupListShowIcons" />    </menu_item_check> -  <menu_item_call -   label="Leave Selected Group" -   layout="topleft" -   name="Leave Selected Group"> -      <menu_item_call.on_click -       function="People.Group.Minus.Action"/> -      <menu_item_call.on_enable -       function="People.Group.Minus.Enable"/> -  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index d2e35e4cc0..b7c9ab1fe3 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -10,12 +10,39 @@           function="Avatar.Profile" />      </menu_item_call>      <menu_item_call +     label="IM" +     layout="topleft" +     name="IM"> +        <menu_item_call.on_click +         function="Avatar.IM" /> +    </menu_item_call> +    <menu_item_call +    label="Offer Teleport" +    name="teleport"> +      <menu_item_call.on_click +       function="Avatar.OfferTeleport"/> +      <menu_item_call.on_enable +      function="Avatar.EnableItem" +      parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_call +     label="Voice call" +     layout="topleft" +     name="Call"> +        <menu_item_call.on_click +         function="Avatar.Call" /> +        <menu_item_call.on_enable +         function="Avatar.EnableItem" +         parameter="can_call" /> +    </menu_item_call> +    <menu_item_separator /> +    <menu_item_call       label="Add Friend"       layout="topleft"       name="Add Friend">          <menu_item_call.on_click           function="Avatar.AddFriend" /> -        <menu_item_call.on_enable +        <menu_item_call.on_visible           function="Avatar.EnableItem"           parameter="can_add" />      </menu_item_call> @@ -30,22 +57,13 @@           parameter="can_delete" />      </menu_item_call>      <menu_item_call -     label="IM" +     label="Invite to group..."       layout="topleft" -     name="IM"> +     name="Invite">          <menu_item_call.on_click -         function="Avatar.IM" /> -    </menu_item_call> -    <menu_item_call -     label="Call" -     layout="topleft" -     name="Call"> -        <menu_item_call.on_click -         function="Avatar.Call" /> -        <menu_item_call.on_enable -         function="Avatar.EnableItem" -         parameter="can_call" /> +         function="Avatar.InviteToGroup" />      </menu_item_call> +    <menu_item_separator />      <menu_item_call       label="Map"       layout="topleft" @@ -83,13 +101,5 @@           function="Avatar.EnableItem"           parameter="can_block" />      </menu_item_check> -    <menu_item_call -    label="Offer Teleport" -    name="teleport"> -      <menu_item_call.on_click -       function="Avatar.OfferTeleport"/> -      <menu_item_call.on_enable -      function="Avatar.EnableItem" -      parameter="can_offer_teleport"/> -    </menu_item_call> +  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml new file mode 100644 index 0000000000..da88ca9f4d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> +    <menu_item_check +       label="Sort by Recent Speakers" +       name="sort_by_recent_speakers"> +      <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +       parameter="sort_by_recent_speakers"/> +      <menu_item_check.on_check +         function="People.Nearby.ViewSort.CheckItem" +         parameter="sort_by_recent_speakers"/> +    </menu_item_check> +    <menu_item_check +       label="Sort by Name" +       name="sort_name"> +      <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +         parameter="sort_name"/> +      <menu_item_check.on_check +         function="People.Nearby.ViewSort.CheckItem" +         parameter="sort_name"/> +    </menu_item_check> +    <menu_item_check +       label="Sort by Distance" +       name="sort_distance"> +      <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +         parameter="sort_distance"/> +      <menu_item_check.on_check +         function="People.Nearby.ViewSort.CheckItem" +         parameter="sort_distance"/> +    </menu_item_check> +    <menu_item_separator layout="topleft" /> +    <menu_item_check name="view_icons" label="View People Icons"> +        <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +         parameter="view_icons" /> +        <menu_item_check.on_check +         function="CheckControl" +         parameter="NearbyListShowIcons" /> +    </menu_item_check> +    <menu_item_check name ="view_map" label="View Map"> +        <menu_item_check.on_check +         function="CheckControl" +         parameter="NearbyListShowMap" /> +        <menu_item_check.on_click +         function="ToggleControl" +         parameter="NearbyListShowMap" /> +    </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml deleted file mode 100644 index 614dd693c5..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu -     name="menu_group_plus" -     left="0" bottom="0" visible="false" -     mouse_opaque="false"> -  <menu_item_check -     label="Sort by Recent Speakers" -     name="sort_by_recent_speakers"> -    <menu_item_check.on_click -       function="People.Nearby.ViewSort.Action" -       parameter="sort_by_recent_speakers"/> -    <menu_item_check.on_check -       function="People.Nearby.ViewSort.CheckItem" -       parameter="sort_by_recent_speakers"/> -  </menu_item_check> -  <menu_item_check -     label="Sort by Name" -     name="sort_name"> -    <menu_item_check.on_click -       function="People.Nearby.ViewSort.Action" -       parameter="sort_name"/> -    <menu_item_check.on_check -       function="People.Nearby.ViewSort.CheckItem" -       parameter="sort_name"/> -  </menu_item_check> -  <menu_item_check -     label="Sort by Distance" -     name="sort_distance"> -    <menu_item_check.on_click -       function="People.Nearby.ViewSort.Action" -       parameter="sort_distance"/> -    <menu_item_check.on_check -       function="People.Nearby.ViewSort.CheckItem" -       parameter="sort_distance"/> -  </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_check name="view_icons" label="View People Icons"> -    <menu_item_check.on_click -     function="People.Nearby.ViewSort.Action" -     parameter="view_icons" /> -    <menu_item_check.on_check -     function="CheckControl" -     parameter="NearbyListShowIcons" /> -  </menu_item_check> -  <menu_item_check name ="view_map" label="View Map"> -    <menu_item_check.on_check -      function="CheckControl" -      parameter="NearbyListShowMap" /> -    <menu_item_check.on_click -      function="ToggleControl" -      parameter="NearbyListShowMap" /> -  </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> -    <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="panel_block_list_sidetray" /> -  </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml index 485a5a658c..1dbc90dd2b 100644 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml @@ -32,8 +32,4 @@       function="CheckControl"       parameter="RecentListShowIcons" />    </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> -    <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="panel_block_list_sidetray" /> -  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index ae5278b7ec..606fdd33d9 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3048,6 +3048,7 @@ Would you like to trust this authority?     icon="alertmodal.tga"     name="GrantedModifyRights"     persist="true" +   log_to_im="true"        type="notify">  [NAME] has given you permission to edit their objects.    </notification> @@ -3056,6 +3057,7 @@ Would you like to trust this authority?     icon="alertmodal.tga"     name="RevokedModifyRights"     persist="true" +   log_to_im="true"        type="notify">  Your privilege to modify [NAME]'s objects has been revoked    </notification> @@ -4240,6 +4242,8 @@ Are you sure you want to change the Estate Covenant?    <notification     icon="notifytip.tga"     name="RegionEntryAccessBlocked_Notify" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">     <tag>fail</tag>  The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. @@ -4248,6 +4252,8 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu    <notification     icon="notifytip.tga"     name="RegionEntryAccessBlocked_NotifyAdultsOnly" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <tag>fail</tag>      The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. @@ -4319,6 +4325,8 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu    <notification     icon="notifytip.tga"     name="TeleportEntryAccessBlocked_Notify" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <unique>        <context>REGIONMATURITY</context> @@ -4330,6 +4338,8 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu    <notification     icon="notifytip.tga"     name="TeleportEntryAccessBlocked_NotifyAdultsOnly" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <unique>        <context>REGIONMATURITY</context> @@ -4450,6 +4460,8 @@ You won't receive any more notifications that you're about to visit a region wit    <notification     icon="notifytip.tga"     name="LandClaimAccessBlocked_Notify" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      The land you're trying to claim contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content.      <tag>fail</tag> @@ -4458,6 +4470,8 @@ You won't receive any more notifications that you're about to visit a region wit    <notification     icon="notifytip.tga"     name="LandClaimAccessBlocked_NotifyAdultsOnly" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <tag>fail</tag>      The land you're trying to claim contains [REGIONMATURITY] content, which is accessible to adults only. @@ -4515,6 +4529,8 @@ You won't receive any more notifications that you're about to visit a region wit    <notification     icon="notifytip.tga"     name="LandBuyAccessBlocked_Notify" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      The land you're trying to buy contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content.      <tag>fail</tag> @@ -4523,6 +4539,8 @@ You won't receive any more notifications that you're about to visit a region wit    <notification     icon="notifytip.tga"     name="LandBuyAccessBlocked_NotifyAdultsOnly" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <tag>fail</tag>      The land you're trying to buy contains [REGIONMATURITY] content, which is accessible to adults only. @@ -4968,6 +4986,20 @@ Go to your [http://secondlife.com/account/ Dashboard] to see your account histor    <notification     icon="alertmodal.tga" +   name="ConfirmAddingChatParticipants" +   type="alertmodal"> +    <unique/> +When you add a person to an existing conversation, a new conversation will be created.  All participants will receive new conversation notifications. +    <tag>confirm</tag> +    <usetemplate +     ignoretext="Confirm adding chat paticipants" +     name="okcancelignore" +     notext="Cancel" +     yestext="Ok"/> +  </notification> +  +  <notification +   icon="alertmodal.tga"     name="ConfirmQuit"     type="alertmodal">      <unique/> @@ -5464,6 +5496,8 @@ The string [STRING_NAME] is missing from strings.xml    <notification     icon="notifytip.tga"     name="IMSystemMessageTip" +   log_to_im="true"    +   log_to_chat="false"        type="notifytip">  [MESSAGE]    </notification> @@ -5507,18 +5541,14 @@ Topic: [SUBJECT], Message: [MESSAGE]    <notification     icon="notifytip.tga" -   name="FriendOnline" +   name="FriendOnlineOffline" +   log_to_chat="false"     type="notifytip">      <tag>friendship</tag> -<nolink>[NAME]</nolink> is Online -  </notification> - -  <notification -   icon="notifytip.tga" -   name="FriendOffline" -   type="notifytip"> -    <tag>friendship</tag> -<nolink>[NAME]</nolink> is Offline +<nolink>[NAME]</nolink> is [STATUS] +    <unique combine="cancel_old"> +      <context>NAME</context> +    </unique>    </notification>    <notification @@ -5762,6 +5792,8 @@ You don't have permission to copy this.    <notification     icon="notifytip.tga"     name="InventoryAccepted" +   log_to_im="true"    +   log_to_chat="false"     type="notifytip">  [NAME] received your inventory offer.    </notification> @@ -5769,6 +5801,8 @@ You don't have permission to copy this.    <notification     icon="notifytip.tga"     name="InventoryDeclined" +   log_to_im="true"    +   log_to_chat="false"     type="notifytip">  [NAME] declined your inventory offer.    </notification> @@ -5850,6 +5884,7 @@ Please select at least one type of content to search (General, Moderate, or Adul    <notification     icon="notify.tga"     name="PaymentReceived" +   log_to_im="true"        persist="true"     type="notify">      <tag>funds</tag> @@ -5859,6 +5894,7 @@ Please select at least one type of content to search (General, Moderate, or Adul    <notification     icon="notify.tga"     name="PaymentSent" +   log_to_im="true"        persist="true"     type="notify">      <tag>funds</tag> @@ -6003,6 +6039,7 @@ The objects on the selected parcel that are NOT owned by you have been returned    <notification     icon="notify.tga"     name="ServerObjectMessage" +   log_to_im="true"        persist="true"     type="notify">  Message from [NAME]: @@ -6421,6 +6458,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="UserGiveItem" +   log_to_im ="true"     type="offer">  [NAME_SLURL] has given you this [OBJECTTYPE]:  [ITEM_SLURL] @@ -6476,6 +6514,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="TeleportOffered" +   log_to_im="true" +   log_to_chat="false"     type="offer">  [NAME_SLURL] has offered to teleport you to their location: @@ -6497,6 +6537,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="TeleportOffered_MaturityExceeded" +   log_to_im="true" +   log_to_chat="false"     type="offer">  [NAME_SLURL] has offered to teleport you to their location: @@ -6520,6 +6562,8 @@ This region contains [REGION_CONTENT_MATURITY] content, but your current prefere    <notification     icon="notify.tga"     name="TeleportOffered_MaturityBlocked" +   log_to_im="true" +   log_to_chat="false"     type="notifytip">  [NAME_SLURL] has offered to teleport you to their location: @@ -6533,6 +6577,9 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="TeleportOfferSent" +   log_to_im="true" +   log_to_chat="false" +   show_toast="false"     type="offer">  	Teleport offer sent to [TO_NAME]    </notification> @@ -6560,6 +6607,7 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="OfferFriendship" +   log_to_im="true"     type="offer">      <tag>friendship</tag>      <tag>confirm</tag> @@ -6583,6 +6631,8 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="FriendshipOffered" +   log_to_im="true"    +   show_toast="false"        type="offer">      <tag>friendship</tag>  	You have offered friendship to [TO_NAME] @@ -6612,6 +6662,7 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="FriendshipAccepted" +   log_to_im="true"        type="offer">      <tag>friendship</tag>  <nolink>[NAME]</nolink> accepted your friendship offer. @@ -6620,6 +6671,7 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="FriendshipDeclined" +   log_to_im="true"        persist="true"     type="notify">      <tag>friendship</tag> @@ -6629,6 +6681,8 @@ However, this region contains content accessible to adults only.      <notification     icon="notify.tga"     name="FriendshipAcceptedByMe" +   log_to_im="true"    +   show_toast="false"     type="offer">      <tag>friendship</tag>  Friendship offer accepted. @@ -6637,6 +6691,8 @@ Friendship offer accepted.    <notification     icon="notify.tga"     name="FriendshipDeclinedByMe" +   log_to_im="true"    +   show_toast="false"        type="offer">      <tag>friendship</tag>  Friendship offer declined. @@ -6686,6 +6742,7 @@ If you stay in this region you will be logged out.    <notification     icon="notify.tga"     name="LoadWebPage" +   show_toast="false"     type="notify">  Load web page [URL]? @@ -6788,6 +6845,7 @@ It is rare that such a request is legitimate. Do not allow access if you do not    <notification     icon="notify.tga"     name="ScriptDialog" +   show_toast="false"     type="notify">  [NAME]'s '<nolink>[TITLE]</nolink>'  [MESSAGE] @@ -6806,6 +6864,7 @@ It is rare that such a request is legitimate. Do not allow access if you do not    <notification     icon="notify.tga"     name="ScriptDialogGroup" +   show_toast="false"     type="notify">      <tag>group</tag>  [GROUPNAME]'s '<nolink>[TITLE]</nolink>' diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml deleted file mode 100644 index d68fa6ca6c..0000000000 --- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - follows="all" - height="215" - name="panel_im_control_panel" - width="150"> -    <layout_stack -     mouse_opaque="false" -     border_size="0" -     clip="false" -     follows="all" -     height="215" -     layout="topleft" -     left="3" -     name="vertical_stack" -     orientation="vertical" -     top="0" -     width="147"> -        <layout_panel -         auto_resize="true" -         follows="top|left" -         height="130" -         layout="topleft" -         left="0" -         min_height="0" -         mouse_opaque="false" -         width="147" -         top="0" -         name="speakers_list_panel"> -            <avatar_list -             color="DkGray2" -             follows="all" -             height="130" -             ignore_online_status="true" -             layout="topleft" -             name="speakers_list" -             opaque="false" -             show_info_btn="true" -             show_profile_btn="false" -             show_speaking_indicator="false" -             width="147" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="130" -         name="call_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="20" -             label="Call" -             name="call_btn" -             width="130" -             top="0" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="130" -         name="end_call_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="20" -             label="Leave Call" -             name="end_call_btn" -             top="0"/> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="130" -         name="voice_ctrls_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="20" -             label="Voice Controls" -             name="voice_ctrls_btn" -             top="0" -             use_ellipses="true" /> -        </layout_panel> -    </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 7c67fd7f83..24f7d44cce 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -4,88 +4,95 @@   follows="left|top|right|bottom"   height="305"   layout="topleft" + left="0"   name="block_list_panel"   help_topic="blocked_list"   min_height="350"   min_width="240" - width="280"> -        <button -     follows="top|left" -     height="24" -     image_hover_unselected="BackButton_Over" -     image_pressed="BackButton_Press" -     image_unselected="BackButton_Off" -     layout="topleft" -     name="back" -     left="4" -     tab_stop="false" -     top="1" -     width="30"/> -    <text -     follows="top|left|right" -     font="SansSerifLargeBold" -     height="20" -     layout="topleft" -     left_pad="10" -     name="title_text" -     text_color="White" -     top="5" -     width="250"> -        Block List -     </text> -    <scroll_list + width="323"> +     <panel +      follows="left|top|right" +      height="27" +      label="bottom_panel" +      layout="topleft" +      left="0" +      name="blocked_buttons_panel" +      right="-1" +      top="0"> +         <filter_editor +          follows="left|top|right" +          height="23" +          layout="topleft" +          left="6" +          label="Filter" +          max_length_chars="300" +          name="blocked_filter_input" +          text_color="Black" +          text_pad_left="10" +          top="4" +          width="177" /> +         <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="OptionsMenu_Off" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="8" +          menu_filename="menu_people_blocked_gear.xml" +          menu_position="bottomleft" +          name="blocked_gear_btn" +          top="3" +          width="31" /> +         <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="Conv_toolbar_sort" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="2" +          menu_filename="menu_people_blocked_view.xml" +          menu_position="bottomleft" +          name="view_btn" +          top_delta="0" +          width="31" /> +         <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="AddItem_Off" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="2" +          menu_filename="menu_people_blocked_plus.xml" +          menu_position="bottomleft" +          name="plus_btn" +          top_delta="0" +          width="31"/> +          <button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="TrashItem_Off" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          left_pad="2" +          layout="topleft" +          name="unblock_btn" +          top_delta="0" +          width="31"/> +     </panel> +    <block_list       follows="all" -     height="190" +     height="273"       layout="topleft" -     left="5" +     left="3"       name="blocked"       tool_tip="List of currently blocked Residents" -     top="30" -     width="270"> -        <scroll_list.columns -         name="item_name" /> -        <scroll_list.columns -         name="item_type" -         width="96" /> -    </scroll_list> -    <button -     follows="left|bottom" -     height="23" -     label="Block person" -     layout="topleft" -     left_delta="0" -     name="Block resident..." -     tool_tip="Pick a Resident to block" -     top_pad="4" -     width="210"> -        <button.commit_callback -         function="Block.ClickPick" /> -    </button> -    <button -     follows="left|bottom" -     height="23" -     label="Block object by name" -     layout="topleft" -     left_delta="0" -     name="Block object by name..." -     tool_tip="Pick an object to block by name" -     top_pad="4" -     width="210" > -        <button.commit_callback -         function="Block.ClickBlockByName" /> -    </button> -    <button -     enabled="false" -     follows="left|bottom" -     height="23" -     label="Unblock" -     layout="topleft" -     left_delta="0" -     name="Unblock" -     tool_tip="Remove Resident or object from blocked list" -     top_pad="4" -     width="210" > -        <button.commit_callback -         function="Block.ClickRemove" /> -    </button> +     top="31" +  	 right="-1"/>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml new file mode 100644 index 0000000000..84e7e467b1 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="23" + layout="topleft" + left="0" + name="blocked_list_item" + top="0" + width="380"> +    <icon +     height="24" +     follows="top|right|left" +     image_name="ListItem_Select" +     layout="topleft" +     left="0" +     name="selected_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     follows="top|right|left" +     height="24" +     image_name="ListItem_Over" +     layout="topleft" +     left="0" +     name="hovered_icon" +     top="0" +     visible="false" +     width="380" /> +    <avatar_icon +     default_icon_name="Generic_Person" +     follows="top|left" +     height="20" +     layout="topleft" +     left="5" +     mouse_opaque="true" +     top="2" +     visible="false" +     width="20" /> +    <group_icon +     default_icon_name="Generic_Group" +     follows="top|left" +     height="20" +     layout="topleft" +     left="5" +     mouse_opaque="true" +     top="2" +     visible="false" +     width="20" /> +    <icon +     follows="top|left" +     height="16" +     image_name="Inv_Object" +     layout="topleft" +     left="7" +     name="object_icon" +     top="4" +     visible="false" +     width="16" /> +    <text +     follows="left|right" +     font="SansSerifSmall" +     font.color="DkGray" +     height="15" +     layout="topleft" +     left_pad="5" +     name="item_name" +     parse_urls="false" +     top="6" +     use_ellipses="true" +     width="180" /> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml new file mode 100644 index 0000000000..cee7d8581a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="23" + layout="topleft" + left="0" + name="conversation_log_list_item" + top="0" + width="380"> +    <icon +     height="24" +     follows="top|right|left" +     image_name="ListItem_Select" +     layout="topleft" +     left="0" +     name="selected_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     follows="top|right|left" +     height="24" +     image_name="ListItem_Over" +     layout="topleft" +     left="0" +     name="hovered_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     default_icon_name="voice_session_icon" +     follows="top|left" +     height="20" +     layout="topleft" +     left="5" +     image_name="Conv_toolbar_open_call" +     mouse_opaque="true" +     name="voice_session_icon" +     top="2" +     visible="false" +     width="20" /> +    <icon +     follows="top|left" +     height="20" +     layout="topleft" +     left="5" +     image_name="Conv_log_inbox" +     mouse_opaque="false" +     name="unread_ims_icon" +     top="2" +     visible="false" +     width="20" /> +    <avatar_icon +     default_icon_name="Generic_Person" +     follows="top|left" +     height="20" +     layout="topleft" +     left_pad="5" +     mouse_opaque="true" +     top="2" +     visible="false" +     width="20" /> +    <group_icon +     default_icon_name="Generic_Group" +     follows="top|left" +     height="20" +     layout="topleft" +     mouse_opaque="true" +     top="2" +     visible="false" +     width="20" /> +    <text +     follows="left|right" +     font="SansSerifSmall" +     font.color="DkGray" +     height="15" +     layout="topleft" +     left_pad="5" +     name="conversation_name" +     parse_urls="false" +     top="6" +     use_ellipses="true" +     width="180" /> +    <text +     follows="right" +     font="SansSerifSmall" +     font.color="DkGray" +     height="15" +     layout="topleft" +     left_pad="5" +     name="date_time" +     parse_urls="false" +     top="6" +     use_ellipses="true" +     width="110"/> +    <button +     name="delete_btn" +     layout="topleft" +     follows="top|right" +     image_unselected="Conv_toolbar_close" +     image_selected="Conv_toolbar_close" +     top="5" +     left_pad="0" +     height="14" +     width="14" +     tab_stop="false"/> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml deleted file mode 100644 index ad10e53a4e..0000000000 --- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml +++ /dev/null @@ -1,109 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - follows="all" - height="238" - name="panel_im_control_panel" - width="150"> -    <layout_stack -     mouse_opaque="false" -     border_size="0" -     clip="false" -     follows="all" -     height="238" -     layout="topleft" -     left="5" -     name="vertical_stack" -     orientation="vertical" -     top="0" -     width="145"> -        <layout_panel -         auto_resize="true" -         follows="top|left" -         height="100" -         layout="topleft" -         min_height="0" -         mouse_opaque="false" -         width="145" -         top="0" -         name="speakers_list_panel"> -            <avatar_list -             color="DkGray2" -             follows="all" -             height="100" -             ignore_online_status="true" -             layout="topleft" -             name="speakers_list" -             opaque="false" -             show_info_btn="true" -             show_profile_btn="false" -             show_speaking_indicator="false" -             width="145" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="group_info_btn_panel"> -            <button -             follows="left|right|bottom" -             height="23" -             label="Group Profile" -             name="group_info_btn" -             use_ellipses="true" -             top="5" -             width="130" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="call_btn_panel"> -            <button -             follows="all" -             height="23" -             label="Call Group" -             name="call_btn" -             use_ellipses="true"  -             width="130" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="end_call_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="23" -             label="Leave Call" -             name="end_call_btn" -             use_ellipses="true" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="voice_ctrls_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="23" -             label="Open Voice Controls" -             name="voice_ctrls_btn" -             use_ellipses="true" /> -        </layout_panel> -    </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_invite.xml b/indra/newview/skins/default/xui/en/panel_group_invite.xml index cd834b61ce..124c0596c3 100644 --- a/indra/newview/skins/default/xui/en/panel_group_invite.xml +++ b/indra/newview/skins/default/xui/en/panel_group_invite.xml @@ -19,6 +19,10 @@       name="already_in_group">          Some Residents you chose are already in the group, and so were not sent an invitation.      </panel.string> +	<panel.string +     name="invite_selection_too_large"> +		Group Invitations not sent: too many Residents selected. Group Invitations are limited to 100 per request. +	</panel.string>      <text       type="string"       length="1" diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml deleted file mode 100644 index 8fcd6ccbaf..0000000000 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ /dev/null @@ -1,166 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - height="300" - name="panel_im_control_panel" - width="150"> -    <avatar_icon -     follows="left|top" -     height="105" -     left_delta="20" -     name="avatar_icon" -     top="-5" -     width="114"/> -    <layout_stack -     mouse_opaque="false" -     border_size="0" -     clip="false" -     follows="all" -     height="183" -     layout="topleft" -     left="5" -     name="button_stack" -     orientation="vertical" -     top_pad="5" -     width="145"> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="20" -         layout="topleft" -         left="2"  -         min_height="20" -         width="140" -         name="view_profile_btn_panel" -         top="0" > -            <button -             follows="left|top|right" -             height="23" -             label="Profile" -             name="view_profile_btn" -             top="0" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="add_friend_btn_panel"> -            <button -             follows="left|top|right" -             height="23" -             label="Add Friend" -             name="add_friend_btn" -             top="5" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="teleport_btn_panel"> -        <button -             auto_resize="false" -             follows="left|top|right" -             height="23" -             label="Teleport" -             name="teleport_btn" -             tool_tip = "Offer to teleport this person" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="share_btn_panel"> -           <button -             auto_resize="true" -             follows="left|top|right" -             height="23" -             label="Share" -             name="share_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="pay_btn_panel"> -           <button -             auto_resize="true" -             follows="left|top|right" -             height="23" -             label="Pay" -             name="pay_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="call_btn_panel"> -            <button -             follows="left|top|right" -             height="23" -             label="Call" -             name="call_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="end_call_btn_panel" -         visible="false"> -            <button -             follows="left|top|right" -             height="23" -             label="End Call" -             name="end_call_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="voice_ctrls_btn_panel" -         visible="false"> -            <button -             follows="left|top|right" -             height="23" -             label="Voice Controls" -             name="voice_ctrls_btn" -             width="140" /> -        </layout_panel> -      <layout_panel -       mouse_opaque="false" -       auto_resize="true" -       follows="top|left" -       height="0" -       layout="topleft" -       min_height="0" -       width="140" -       name="spacer"/> -    </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml index 413e22e444..433a3181cd 100644 --- a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml @@ -2,7 +2,7 @@  <inbox_inventory_panel      accepts_drag_and_drop="false"      name="inventory_inbox" -    start_folder="Received Items" +    start_folder.type="inbox"      follows="all" layout="topleft"      top="0" left="0" height="165" width="308"      top_pad="0" diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 2a5933e3e9..67a09949ce 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -35,7 +35,9 @@               left="0"               mouse_opaque="true"               name="favorites_list" -             start_folder="Favorites" +             scroll.hide_scrollbar="true" +             folder_view.use_ellipses="true" +             start_folder.name="Favorites"               width="307"/>          </accordion_tab>          <accordion_tab @@ -51,7 +53,9 @@               left="0"               mouse_opaque="true"               name="landmarks_list" -             start_folder="Landmarks" +             scroll.hide_scrollbar="true" +             folder_view.use_ellipses="true" +             start_folder.name="Landmarks"               width="307"/>          </accordion_tab>          <accordion_tab @@ -67,7 +71,9 @@               left="0"               mouse_opaque="true"               name="my_inventory_list" -             start_folder="My Inventory" +             scroll.hide_scrollbar="true" +             folder_view.use_ellipses="true" +             start_folder.name="My Inventory"               width="307"/>            </accordion_tab>            <accordion_tab @@ -83,7 +89,9 @@               left="0"               mouse_opaque="true"               name="library_list" -             start_folder="LIBRARY" +             scroll.hide_scrollbar="true" +             folder_view.use_ellipses="true" +             start_folder.name="LIBRARY"               width="313"/>          </accordion_tab>      </accordion> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml index d683116eb8..4de56b424e 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml @@ -1,20 +1,22 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel   follows="all" - height="300" + top="0" + bottom_delta="10"   help_topic="nearby_chat"   layout="topleft"   name="nearby_chat" - width="320"> + width="242" + height="169">    <layout_stack     follows="all" -   height="295" +   height="164"     layout="topleft"     left="0"     name="stack"     top="5"     orientation="vertical" -   width="320"> +   width="242">      <layout_panel       auto_resize="false"       height="26" @@ -23,7 +25,7 @@       name="translate_chat_checkbox_lp"       top_delta="0"       visible="true" -     width="313"> +     width="230">        <check_box         top="10"         control_name="TranslateChat" @@ -33,15 +35,15 @@         layout="topleft"         left="5"         name="translate_chat_checkbox" -       width="300" /> +       width="230" />      </layout_panel>      <layout_panel       auto_resize="true" -     height="277" +     height="138"       left_delta="0"       layout="topleft"       name="chat_history_lp" -     width="318"> +     width="242">        <chat_history         bg_readonly_color="ChatHistoryBgColor"         bg_writeable_color="ChatHistoryBgColor" @@ -49,7 +51,7 @@         layout="topleft"         left="5"         left_widget_pad="0" -       height="272" +       height="138"         name="chat_history"         parse_highlights="true"         parse_urls="true" @@ -57,7 +59,7 @@         text_color="ChatHistoryTextColor"         text_readonly_color="ChatHistoryTextColor"         top="0" -       width="313" /> +       width="237" />      </layout_panel>    </layout_stack>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml index a3d39e55af..203febbf18 100644 --- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml @@ -1,7 +1,10 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_inventory_panel +<inventory_panel      name="inventory_outbox" -    start_folder="Outbox" +    start_folder.name="Outbox" +    show_empty_message="false" +    show_load_status="false" +    start_folder.type="outbox"      follows="all" layout="topleft"      top="0" left="0" height="165" width="308"      top_pad="0" @@ -12,6 +15,11 @@      bevel_style="none"      show_item_link_overlays="true"      tool_tip="Drag and drop items here to prepare them for sale on your storefront" -    > -    <scroll reserve_scroll_corner="false" /> -</outbox_inventory_panel> +    scroll.reserve_scroll_corner="false"> +      <folder folder_arrow_image="Folder_Arrow" +              folder_indentation="8" +              item_height="20" +              item_top_pad="4" +              selection_image="Rounded_Square"/> +      <item allow_open="false"/> +</inventory_panel> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 98c7c49ff4..09156b41b5 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -38,12 +38,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M       name="no_filtered_friends_msg">           Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search].      </string> -    <string -     name="people_filter_label" -     value="Filter People" /> -    <string -     name="groups_filter_label" -     value="Filter Groups" />       <!--       *WORKAROUND: for group_list.no_items_msg & group_list.no_filtered_items_msg attributes.       They are not defined as translatable in VLT. See EXT-5931 @@ -60,21 +54,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M  	<string  	 name="AltMiniMapToolTipMsg"  	 value="[REGION](Double-click to teleport, shift-drag to pan)"/> -	<filter_editor -     follows="left|top|right" -     height="23" -     layout="topleft" -     left="10" -     label="Filter" -     max_length_chars="300" -     name="filter_input" -     text_color="Black" -     text_pad_left="10" -     top="3" -     width="303" />      <tab_container +     bottom="-10"       follows="all" -     height="383"       layout="topleft"       left="3"       name="tabs" @@ -82,31 +64,116 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M       tab_min_width="70"       tab_height="30"       tab_position="top" -     top_pad="10" +     top="0"       halign="center" -     width="319"> -     	<panel +     right="-5"> + +<!-- ================================= NEARBY tab =========================== --> + +        <panel           background_opaque="true"           background_visible="true"           bg_alpha_color="DkGray"           bg_opaque_color="DkGray" +         bottom="-1"           follows="all" -         height="383"           label="NEARBY"           layout="topleft"           left="0"           help_topic="people_nearby_tab"           name="nearby_panel" -         top="0" -         width="313"> +         right="-1" +         top="0"> +            <panel +             follows="left|top|right" +             height="27" +             label="bottom_panel" +             layout="topleft" +             left="0" +             name="nearby_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter People" +                 max_length_chars="300" +                 name="nearby_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="178" /> +                <button +                 commit_callback.function="People.Gear" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="7" +                 name="gear_btn" +                 top="3" +                 width="31" /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_sort" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_people_nearby_view.xml" +                 menu_position="bottomleft" +                 name="nearby_view_btn" +                 top_delta="0" +                 width="31" /> +                <button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 name="add_friend_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.AddFriend" /> +                </button> +                <dnd_button +                 enabled="false" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="nearby_del_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.DelFriend" /> +                 </dnd_button> +            </panel>           <layout_stack             clip="false"             follows="all" -           height="355" +           height="410"             layout="topleft" +           left="0"             mouse_opaque="false"             orientation="vertical" -           width="313"> +           right="-1" +           top_pad="0">             <layout_panel               height="142"               layout="topleft" @@ -123,16 +190,16 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                 left="3"                 mouse_opaque="false"                 name="Net Map" -               top="4" -               width="305"/> +               right="-1" +               top="4" />             </layout_panel>             <layout_panel               height="213"               layout="topleft"               min_dim="100"               mouse_opaque="false" -             user_resize="true" -             width="313"> +             right="-1" +             user_resize="true">               <avatar_list                 allow_select="true"                 follows="all" @@ -143,84 +210,118 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                 keep_one_selected="false"                 multi_select="true"                 name="avatar_list" -               top="2" -               width="306" /> +               right="-1" +               top="2" />             </layout_panel>           </layout_stack> -         <panel -             background_visible="true" -             follows="left|right|bottom" -             height="27" -             label="bottom_panel" -             layout="topleft" -             left="3" -             name="bottom_panel" -             top_pad="0" -             width="313"> -             <menu_button -             follows="bottom|left" -             height="25" -             image_hover_unselected="Toolbar_Left_Over" -             image_overlay="OptionsMenu_Off" -             image_selected="Toolbar_Left_Selected" -             image_unselected="Toolbar_Left_Off" -             layout="topleft" -             left="0" -             name="nearby_view_sort_btn" -             tool_tip="Options" -             top="1" -             width="31" /> -             <button -                 follows="bottom|left" -                 height="25" -                 image_hover_unselected="Toolbar_Middle_Over" -             	 image_overlay="AddItem_Off" -                 image_selected="Toolbar_Middle_Selected" -             	 image_unselected="Toolbar_Middle_Off" -                 layout="topleft" -                 left_pad="1" -                 name="add_friend_btn" -                 tool_tip="Add selected Resident to your friends List" -                 width="31"> -               <commit_callback -                  function="People.addFriend" /> -             </button> -             <icon -             follows="bottom|left|right" -             height="25" -             image_name="Toolbar_Right_Off" -             layout="topleft" -             left_pad="1" -             name="dummy_icon" -             width="243" -             /> -            </panel>          </panel> + +<!-- ================================= FRIENDS tab ========================== --> +          <panel           background_opaque="true"         background_visible="true"           bg_alpha_color="DkGray"           bg_opaque_color="DkGray" +         bottom="-1"           follows="all" -         height="383"           label="MY FRIENDS"           layout="topleft"           left="0"           help_topic="people_friends_tab"           name="friends_panel" -         top="0" -         width="313"> +         right="-1" +         top="0"> +            <panel +             follows="left|top|right" +             height="27" +             label="bottom_panel" +             layout="topleft" +             left="0" +             name="friends_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter People" +                 max_length_chars="300" +                 name="friends_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="177" /> +                <button +                 commit_callback.function="People.Gear" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="8" +                 name="gear_btn" +                 top="3" +                 width="31" /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_sort" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_people_friends_view.xml" +                 menu_position="bottomleft" +                 name="friends_view_btn" +                 top_delta="0" +                 width="31" /> +                <button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 name="friends_add_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.AddFriendWizard" /> +                </button> +                <dnd_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="friends_del_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.DelFriend" /> +                </dnd_button> +            </panel>              <accordion         		 background_visible="true"         		 bg_alpha_color="DkGray2"         		 bg_opaque_color="DkGray2"               follows="all" -             height="356" +             height="408"               layout="topleft"               left="3"               name="friends_accordion" -             top="0" -             width="307"> +             right="-2" +             top_pad="2">                  <accordion_tab                   layout="topleft"                   height="172" @@ -257,247 +358,129 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                           width="307" />                  </accordion_tab>              </accordion> -            <panel -             background_visible="true" -             follows="left|right|bottom" -             height="27" -             label="bottom_panel" -             layout="topleft" -             left="3" -             name="bottom_panel" -             top_pad="0" -             width="313"> -              -             	  <layout_stack -				   animate="false" -				   border_size="0" -				   follows="left|right|bottom" -				   height="25" -				   layout="topleft" -				   orientation="horizontal" -				   top_pad="1" -				   left="0" -				   name="bottom_panel" -				   width="308"> -				      <layout_panel -				       auto_resize="false" -				       height="25" -				       layout="topleft" -				       name="options_gear_btn_panel" -				       width="32"> -				          <menu_button -				           follows="bottom|left" -				           tool_tip="Show additional options" -				           height="25" -				           image_hover_unselected="Toolbar_Left_Over" -				           image_overlay="OptionsMenu_Off" -				           image_selected="Toolbar_Left_Selected" -				           image_unselected="Toolbar_Left_Off" -				           layout="topleft" -				           left="0" -				           name="friends_viewsort_btn" -				           top="0" -				           width="31" /> -				      </layout_panel> -				      <layout_panel -				       auto_resize="false" -				       height="25" -				       layout="topleft" -				       name="add_btn_panel" -				       width="32"> -				          <button -				           follows="bottom|left" -				           height="25" -				           image_hover_unselected="Toolbar_Middle_Over" -				           image_overlay="AddItem_Off" -				           image_selected="Toolbar_Middle_Selected" -				           image_unselected="Toolbar_Middle_Off" -				           layout="topleft" -				           left="0" -				           name="add_btn" -				           tool_tip="Offer friendship to a Resident" -				           top="0" -				           width="31" /> -				      </layout_panel> -				      <layout_panel -				       auto_resize="true" -				       height="25" -				       layout="topleft" -				       name="dummy_panel" -				       width="210"> -				          <icon -				           follows="bottom|left|right" -				           height="25" -				           image_name="Toolbar_Middle_Off" -				           layout="topleft" -				           left="0" -				           top="0" -				           name="dummy_icon" -				           width="210" /> -				      </layout_panel> -				      <layout_panel -				       auto_resize="false" -				       height="25" -				       layout="topleft" -				       name="trash_btn_panel" -				       width="31"> -				          <dnd_button -				           follows="bottom|left" -				           height="25" -				           image_hover_unselected="Toolbar_Right_Over" -				           image_overlay="TrashItem_Off" -				           image_selected="Toolbar_Right_Selected" -				           image_unselected="Toolbar_Right_Off" -				           left="0" -				           layout="topleft" -				           name="del_btn" -				           tool_tip="Remove selected person from your Friends list" -				           top="0" -				           width="31"/> -				      </layout_panel> -				  </layout_stack><!-- -              -               <button -               follows="bottom|left" -               tool_tip="Options" -               height="25" -               image_hover_unselected="Toolbar_Left_Over" -               image_overlay="OptionsMenu_Off" -               image_selected="Toolbar_Left_Selected" -               image_unselected="Toolbar_Left_Off" -               layout="topleft" -               left="0" -               name="friends_viewsort_btn" -               top="1" -               width="31" /> -                <button -                 follows="bottom|left" -                 height="25" -                 image_hover_unselected="Toolbar_Middle_Over" -             	 image_overlay="AddItem_Off" -             	 image_selected="Toolbar_Middle_Selected" -             	 image_unselected="Toolbar_Middle_Off" -                 layout="topleft" -                 left_pad="1" -                 name="add_btn" -                 tool_tip="Offer friendship to a Resident" -                 width="31" /> -                <icon -             	 follows="bottom|left|right" -             	 height="25" -             	 image_name="Toolbar_Middle_Off" -             	 layout="topleft" -             	 left_pad="1" -             	 name="dummy_icon" -             	 width="209" -             /> -                <button -                 follows="bottom|left" -                 height="25" -                 image_hover_unselected="Toolbar_Right_Over" -                 image_overlay="TrashItem_Off" -                 image_selected="Toolbar_Right_Selected" -                 image_unselected="Toolbar_Right_Off" -                 layout="topleft" -                 left_pad="1" -                 name="del_btn" -                 tool_tip="Remove selected person from your Friends list" -                 width="31" /> -            --></panel>              <text               follows="all"               height="450"               left="13"               name="no_friends_help_text" -             top="10" -             width="293" +             right="-13" +             top="37"               wrap="true" />          </panel> + +<!-- ================================= GROUPS tab =========================== --> +          <panel           background_opaque="true"         background_visible="true"           bg_alpha_color="DkGray"           bg_opaque_color="DkGray" +         bottom="-1"           follows="all" -         height="383"           label="MY GROUPS"           layout="topleft"           left="0"           help_topic="people_groups_tab"           name="groups_panel" -         top="0" -         width="313"> +         right="-1" +         top="0">      <!--       *NOTE: no_groups_msg & group_list attributes are not defined as translatable in VLT. See EXT-5931       Values are set from appropriate strings at the top of file via LLPeoplePanel::postBuild()      --> -            <group_list -             allow_select="true"  -             follows="all" -             height="356" -             layout="topleft" -             left="3" -             name="group_list" -             top="0" -             width="307" />              <panel -             background_visible="true" -             follows="left|right|bottom" +             follows="left|top|right"               height="27"               label="bottom_panel"               layout="topleft"               left="0" -             name="bottom_panel" -             top_pad="0" -             width="313"> -               <menu_button -               follows="bottom|left" -               tool_tip="Options" -               height="25" -               image_hover_unselected="Toolbar_Left_Over" -               image_overlay="OptionsMenu_Off" -               image_selected="Toolbar_Left_Selected" -               image_unselected="Toolbar_Left_Off" -               layout="topleft" -               left="3" -               name="groups_viewsort_btn" -               top="1" -               width="31" /> -                <button -                 follows="bottom|left" +             name="groups_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter Groups" +                 max_length_chars="300" +                 name="groups_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="177" /> +                <menu_button +                 follows="right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over" -                 image_overlay="AddItem_Off" +                 image_overlay="OptionsMenu_Off"                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 left_pad="1" -                 name="plus_btn" -                 tool_tip="Join group/Create new group" +                 left_pad="8" +                 name="groups_gear_btn" +                 top="3"                   width="31" /> -                <button -                 follows="bottom|left" +                <menu_button +                 follows="right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over" -                 image_overlay="Activate_Checkmark" +                 image_overlay="Conv_toolbar_sort"                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 left_pad="1" -                 name="activate_btn" -                 tool_tip="Activate selected group" +                 left_pad="2" +                 menu_filename="menu_people_groups_view.xml" +                 menu_position="bottomleft" +                 name="groups_view_btn" +                 top_delta="0"                   width="31" /> -                 <icon -             	 follows="bottom|left|right" -             	 height="25" -             	 image_name="Toolbar_Right_Off" -             	 layout="topleft" -             	 left_pad="1" -             	 name="dummy_icon" -             	 width="212" -             /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_group_plus.xml" +                 menu_position="bottomleft" +                 name="plus_btn" +                 top_delta="0" +                 width="31"> +                    <validate_callback +                     function="People.Group.Plus.Validate" /> +                </menu_button> +                <dnd_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="minus_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.Group.Minus" /> +                </dnd_button>              </panel> +            <group_list +             allow_select="true"  +             follows="all" +             height="406" +             layout="topleft" +             left="3" +             name="group_list" +             right="-2" +             top_pad="4" />          </panel> + +<!-- ================================= RECENT tab =========================== --> +          <panel           background_opaque="true"         background_visible="true" @@ -510,265 +493,129 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M           left="0"           help_topic="people_recent_tab"           name="recent_panel" -         top="0" -         width="313"> -            <avatar_list -             allow_select="true" -             follows="all" -             height="356" -             layout="topleft" -             left="3" -             multi_select="true" -             name="avatar_list" -             show_last_interaction_time="true" -             top="0" -             width="307" /> +         right="-1" +         top="0">              <panel -             background_visible="true" -             follows="left|right|bottom" +             follows="left|top|right"               height="27"               label="bottom_panel"               layout="topleft" -             left="3" -             name="bottom_panel" -             top_pad="0" -             width="313"> -               <menu_button -               follows="bottom|left" -               tool_tip="Options" -               height="25" -               image_hover_unselected="Toolbar_Left_Over" -               image_overlay="OptionsMenu_Off" -               image_selected="Toolbar_Left_Selected" -               image_unselected="Toolbar_Left_Off" -               layout="topleft" -               name="recent_viewsort_btn" -               top="1" -               width="31" /> -              <button -                 follows="bottom|left" +             left="0" +             name="recent_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter People" +                 max_length_chars="300" +                 name="recent_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="177" /> +                <button +                 commit_callback.function="People.Gear" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="8" +                 name="gear_btn" +                 top="3" +                 width="31" /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_sort" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_people_recent_view.xml" +                 menu_position="bottomleft" +                 name="recent_view_btn" +                 top_delta="0" +                 width="31" /> +                <button +                 follows="right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over"                   image_overlay="AddItem_Off"                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 left_pad="1" +                 left_pad="2"                   name="add_friend_btn" -                 tool_tip="Add selected Resident to your friends List" +                 top_delta="0"                   width="31"> -                <commit_callback -                   function="People.addFriend" /> -              </button> -              <icon -             	 follows="bottom|left|right" -             	 height="25" -             	 image_name="Toolbar_Right_Off" -             	 layout="topleft" -             	 left_pad="1" -             	 name="dummy_icon" -             	 width="244" -             /> +                    <commit_callback +                     function="People.AddFriend" /> +                </button> +                <dnd_button +                 enabled="false" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="recent_del_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.DelFriend" /> +                 </dnd_button>              </panel> +            <avatar_list +             allow_select="true" +             follows="all" +             height="351" +             layout="topleft" +             left="3" +             multi_select="true" +             name="avatar_list" +             show_last_interaction_time="true" +             right="-2" +             top_pad="4" />          </panel> -    </tab_container> -    <panel -     follows="bottom|left|right" -     height="23" -     layout="topleft" -     left="8" -     top_pad="4" -     name="button_bar" -     width="313"> -<!--********************************Profile; IM; Call, Share, Teleport********************************--> 	 -     	<layout_stack -     	follows="bottom|left|right" -		height="23" -		layout="topleft" -		name="bottom_bar_ls" -		left="0" -		orientation="horizontal" -		top_pad="0" -		width="313"> +<!-- ================================= BLOCKED tab ========================== --> -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left="0" -			name="view_profile_btn_lp" -		    auto_resize="true" -			width="68"> -				<button -		         follows="bottom|left|right" -		         height="23" -		         label="Profile" -		         layout="topleft" -		         left="1" -		         name="view_profile_btn" -		         tool_tip="Show picture, groups, and other Residents information" -		         top="0" -		         width="67" />	 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="im_btn_lp" -		    auto_resize="true" -			width="41"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="IM" -		         layout="topleft" -		         name="im_btn" -		         tool_tip="Open instant message session" -		         top="0" -		         width="40" />			 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="call_btn_lp" -		    auto_resize="true" -			width="52"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="Call" -		         layout="topleft" -		         name="call_btn" -		         tool_tip="Call this Resident" -		         top="0" -		         width="51" />		 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="share_btn_lp" -		    auto_resize="true" -			width="66"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="Share" -		         layout="topleft" -		         name="share_btn" -		         tool_tip="Share an inventory item" -		         top="0" -		         width="65" />	 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="teleport_btn_lp" -		    auto_resize="true" -			width="77"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="Teleport" -		         layout="topleft" -		         name="teleport_btn" -		         tool_tip="Offer teleport" -		         top="0" -		         width="76" />		 -			</layout_panel> -		</layout_stack> -		 -<!--********************************Group Profile; Group Chat; Group Call buttons************************-->			 -		<layout_stack -     	follows="bottom|left|right" -		height="23" -		layout="topleft" -		mouse_opaque="false" -		name="bottom_bar_ls1" -		left="0" -		orientation="horizontal" -		top="0" -		width="313">	 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left="0"			 -			mouse_opaque="false" -			name="group_info_btn_lp" -		    auto_resize="true" -			width="108"> -				<button -		        follows="bottom|left|right" -		        left="1" -		        height="23" -		        label="Group Profile" -		        layout="topleft" -				mouse_opaque="false" -		        name="group_info_btn" -		        tool_tip="Show group information" -		        top="0" -		        width="107" />		 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			mouse_opaque="false" -			name="chat_btn_lp" -		    auto_resize="true" -			width="101"> -				<button -		        follows="bottom|left|right" -		        left="1" -		        height="23" -		        label="Group Chat" -		        layout="topleft" -				mouse_opaque="false" -		        name="chat_btn" -		        tool_tip="Open chat session" -		        top="0" -		        width="100" />			 -			</layout_panel> -		 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			mouse_opaque="false" -			name="group_call_btn_lp" -		    auto_resize="true" -			width="96"> -				<button -				follows="bottom|left|right" -				left="1" -				height="23" -         		label="Group Call" -         		layout="topleft" -				mouse_opaque="false" -         		name="group_call_btn" -         		tool_tip="Call this group" -		        top="0" -         		width="95" />			 -			</layout_panel>		 -		</layout_stack> -    </panel> +        <panel +         background_opaque="true" +         background_visible="true" +         bg_alpha_color="DkGray" +         bg_opaque_color="DkGray" +         follows="all" +         height="383" +         label="BLOCKED" +         layout="topleft" +         left="0" +         help_topic="people_blocked_tab" +         name="blocked_panel" +         right="-1" +         top="0"> +          <panel +           class="panel_block_list_sidetray" +           height="383" +           name="panel_block_list_sidetray" +           filename="panel_block_list_sidetray.xml" +           follows="all" +           label="Blocked Residents & Objects" +           layout="topleft" +           left="0" +           font="SansSerifBold" +           top="0" +           right="-1" /> +        </panel> +    </tab_container>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 27193a984f..c76a3cfaaf 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -76,15 +76,6 @@       top_pad="5"       width="400" />      <check_box -     enabled="false" -     height="16" -     label="Enable plain text IM and chat history" -     layout="topleft" -     left_delta="0" -     name="plain_text_chat_history" -     top_pad="5" -     width="400" /> -    <check_box       control_name="UseChatBubbles"       follows="left|top"       height="16" @@ -95,55 +86,6 @@       name="bubble_text_chat"       width="150" />           <text -     name="show_ims_in_label" -     follows="left|top" -     layout="topleft" -     left="30" -     height="20" -     width="170" -     top_pad="15"> -     Show IMs in: -    </text> -    <text -     name="requires_restart_label" -     follows="left|top" -     layout="topleft" -     top_delta="0"  -     left="170"  -  	 height="20" -	 width="130" -     text_color="White_25"> -      (requires restart) -      </text> -    <radio_group -     follows="left|top" -     height="30" -     left="40" -     control_name="ChatWindow" -     name="chat_window" -     top_pad="0" -     tool_tip="Show your Instant Messages in separate floaters, or in one floater with many tabs (Requires restart)" -     width="150"> -     <radio_item -      height="16" -      label="Separate Windows" -      layout="topleft" -      left="0" -      name="radio" -      value="0" -      top="0" -      width="150" /> -     <radio_item -      height="16" -      label="Tabs" -      layout="topleft" -      left_delta="0" -      name="radio2" -      value="1" -      top_pad="5" -      width="150" /> -    </radio_group> -    <text       name="disable_toast_label"       follows="left|top"       layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_region_debug.xml b/indra/newview/skins/default/xui/en/panel_region_debug.xml index 4550603134..a4883c21e2 100644 --- a/indra/newview/skins/default/xui/en/panel_region_debug.xml +++ b/indra/newview/skins/default/xui/en/panel_region_debug.xml @@ -194,7 +194,7 @@      <button       follows="left|top"       height="20" -     label="Delay Restart" +     label="Cancel Restart"       layout="topleft"       left_pad="155"       name="cancel_restart_btn" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index d5186e4c1b..696c282887 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -384,13 +384,14 @@ Please try logging in again in a minute.</string>  	<string name="ST_NO_JOINT">Can't find ROOT or JOINT.</string>  	<!-- Chat --> +	<string name="NearbyChatTitle">Nearby chat</string>  	<string name="whisper">whispers:</string>  	<string name="shout">shouts:</string>  	<string name="ringing">Connecting to in-world Voice Chat...</string>  	<string name="connected">Connected</string>  	<string name="unavailable">Voice not available at your current location</string>  	<string name="hang_up">Disconnected from in-world Voice Chat</string> -  <string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string> +    <string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string>  	<string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string>  	<string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string>  	<string name="AdditionalPermissionsRequestHeader">If you allow access to your account, you will also be allowing the object to:</string> @@ -404,9 +405,10 @@ Please try logging in again in a minute.</string>  	<string name="AddAndRemoveJoints">Add and remove joints with other objects</string>  	<string name="ChangePermissions">Change its permissions</string>  	<string name="TrackYourCamera">Track your camera</string> -  <string name="ControlYourCamera">Control your camera</string> -  <string name="TeleportYourAgent">Teleport you</string> -  <string name="NotConnected">Not Connected</string> +	<string name="ControlYourCamera">Control your camera</string> +	<string name="NotConnected">Not Connected</string> +	<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> +    <string name="TeleportYourAgent">Teleport you</string>  	<!-- Sim Access labels -->  	<string name="SIM_ACCESS_PG">General</string> @@ -2270,8 +2272,10 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale  	<string name="InvFolder Gestures">Gestures</string>  	<string name="InvFolder Favorite">My Favorites</string>    <!-- historically default name of the Favorites folder can start from either "f" or "F" letter. -  We should localize both of them with the same value --> +      Also, it can be written as "Favorite" or "Favorites". +  We should localize all variants of them with the same value -->  	<string name="InvFolder favorite">My Favorites</string> +	<string name="InvFolder Favorites">My Favorites</string>  	<string name="InvFolder Current Outfit">Current Outfit</string>  	<string name="InvFolder Initial Outfits">Initial Outfits</string>  	<string name="InvFolder My Outfits">My Outfits</string> @@ -2280,6 +2284,7 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale    <!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->  	<string name="InvFolder Friends">Friends</string> +	<string name="InvFolder Received Items">Received Items</string>  	<string name="InvFolder All">All</string>  	<string name="no_attachments">No attachments worn</string> @@ -2579,9 +2584,6 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale  	<string name="GroupMoneyDebits">Debits</string>  	<string name="GroupMoneyDate">[weekday,datetime,utc] [mth,datetime,utc] [day,datetime,utc], [year,datetime,utc]</string> -	<!-- viewer object --> -	<string name="ViewerObjectContents">Contents</string> -  	<!-- Viewer menu -->  	<string name="AcquiredItems">Acquired Items</string>  	<string name="Cancel">Cancel</string> @@ -3377,6 +3379,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	<string name="IM_moderator_label">(Moderator)</string>  	<string name="Saved_message">(Saved [LONG_TIMESTAMP])</string>  	<string name="IM_unblock_only_groups_friends">To see this message, you must uncheck 'Only friends and groups can call or IM me' in Preferences/Privacy.</string> +  <string name="OnlineStatus">Online</string> +  <string name="OfflineStatus">Offline</string>  	<!-- voice calls -->  	<string name="answered_call">Your call has been answered</string> @@ -3823,6 +3827,7 @@ Try enclosing path to the editor with double quotes.    <string name="Command_Avatar_Label">Avatar</string>    <string name="Command_Build_Label">Build</string>    <string name="Command_Chat_Label">Chat</string> +  <string name="Command_Conversations_Label">Conversations</string>    <string name="Command_Compass_Label">Compass</string>    <string name="Command_Destinations_Label">Destinations</string>    <string name="Command_Gestures_Label">Gestures</string> @@ -3849,6 +3854,7 @@ Try enclosing path to the editor with double quotes.    <string name="Command_Avatar_Tooltip">Choose a complete avatar</string>    <string name="Command_Build_Tooltip">Building objects and reshaping terrain</string>    <string name="Command_Chat_Tooltip">Chat with people nearby using text</string> +  <string name="Command_Conversations_Tooltip">Converse with everyone</string>    <string name="Command_Compass_Tooltip">Compass</string>    <string name="Command_Destinations_Tooltip">Destinations of interest</string>    <string name="Command_Gestures_Tooltip">Gestures for your avatar</string> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_editor.xml b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml new file mode 100644 index 0000000000..f9facb593a --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chat_editor +  name="chat_editor" +  show_context_menu="true"/> diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml index 830c27bdac..d5b10e7f51 100644 --- a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml +++ b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml @@ -1,2 +1,3 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<inbox_inventory_panel show_load_status="false" /> +<inbox_inventory_panel show_load_status="false" +                       start_folder.type="inbox"/> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml deleted file mode 100644 index d19c47f54f..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_folder_view_folder -  folder_arrow_image="Folder_Arrow" -  folder_indentation="8" -  item_height="20"  -  item_top_pad="4" -  selection_image="Rounded_Square" -  > -</outbox_folder_view_folder> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml deleted file mode 100644 index 3964569da2..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_inventory_panel show_empty_message="false" show_load_status="false" /> diff --git a/indra/newview/skins/default/xui/en/widgets/text.xml b/indra/newview/skins/default/xui/en/widgets/text.xml index 134f2d7522..2102074674 100644 --- a/indra/newview/skins/default/xui/en/widgets/text.xml +++ b/indra/newview/skins/default/xui/en/widgets/text.xml @@ -9,6 +9,7 @@        h_pad="0"         allow_scroll="false"        text_readonly_color="LabelTextColor" +      text_tentative_color="TextFgTentativeColor"        bg_writeable_color="FloaterDefaultBackgroundColor"         use_ellipses="false"        bg_visible="false"  diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml index 49af1a87e1..c86f31b429 100644 --- a/indra/newview/skins/default/xui/fr/floater_about_land.xml +++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml @@ -134,7 +134,7 @@  			<text name="DwellText">  				Chargement...  			</text> -			<button label="Acheter du terrain" label_selected="Acheter le terrain..." left_delta="60" name="Buy Land..." width="125"/> +			<button label="Acheter le terrain" label_selected="Acheter le terrain..." left_delta="60" name="Buy Land..." width="125"/>  			<button label="Vente Linden" label_selected="Vente Linden..." name="Linden Sale..." tool_tip="Le terrain doit être la propriété d'un résident, avoir un contenu défini et ne pas être aux enchères."/>  			<button label="Infos sur les scripts" name="Scripts..." width="110"/>  			<button label="Acheter pour le groupe" label_selected="Acheter pour le groupe..." name="Buy For Group..."/> @@ -377,7 +377,7 @@ Seules les parcelles de grande taille peuvent apparaître dans la recherche.  			</text>  			<texture_picker label="" name="snapshot_ctrl" tool_tip="Cliquez pour sélectionner une image"/>  			<text name="allow_label5"> -				Les avatars présents sur d'autres parcelles peuvent voir et chatter avec les avatars présents sur cette parcelle. +				Les avatars sur d'autres parcelles peuvent voir et chatter avec les avatars sur cette parcelle.  			</text>  			<check_box label="Voir les avatars" name="SeeAvatarsCheck" tool_tip="Permettre aux avatars présents sur d'autres parcelles de voir et chatter avec les avatars présents sur cette parcelle et à vous de les voir et de chatter avec eux."/>  			<text name="landing_point"> diff --git a/indra/newview/skins/default/xui/fr/floater_camera.xml b/indra/newview/skins/default/xui/fr/floater_camera.xml index f2b0ee8af3..893e389f69 100644 --- a/indra/newview/skins/default/xui/fr/floater_camera.xml +++ b/indra/newview/skins/default/xui/fr/floater_camera.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="camera_floater" title="PARAMÈTRES DE LA CAMÉRA"> +<floater name="camera_floater" title="CONTRÔLE DE LA CAMÉRA">  	<floater.string name="rotate_tooltip">  		Faire tourner la caméra autour du point central  	</floater.string> diff --git a/indra/newview/skins/default/xui/fr/floater_edit_day_cycle.xml b/indra/newview/skins/default/xui/fr/floater_edit_day_cycle.xml index 0100419bc5..de1ba220a0 100644 --- a/indra/newview/skins/default/xui/fr/floater_edit_day_cycle.xml +++ b/indra/newview/skins/default/xui/fr/floater_edit_day_cycle.xml @@ -22,13 +22,13 @@  		Remarque : si vous changez votre préréglage de nom, un nouveau préréglage sera créé et celui existant restera tel quel.  	</text>  	<text name="hint_item1"> -		- Cliquez sur un repère pour modifier le réglage du ciel et l'heure associés. +		- Modifier un réglage de ciel et d'heure : clic sur le repère  	</text>  	<text name="hint_item2"> -		- Cliquez sur les repères et faites-les glisser afin de définir les heures de transition. +		- Définir les heures de transition : clic et glissement des repères  	</text>  	<text name="hint_item3"> -		- Déplacez le marqueur en forme de triangle pour afficher un aperçu du cycle du jour. +		- Afficher un aperçu du cycle du jour : déplacer le triangle  	</text>  	<panel name="day_cycle_slider_panel">  		<multi_slider initial_value="0" name="WLTimeSlider"/> @@ -91,11 +91,11 @@  		</text>  	</panel>  	<text name="WLCurKeyPresetText"> -		Réglage du ciel : +		Régl. ciel :  	</text>  	<combo_box label="Préréglage" name="WLSkyPresets"/>  	<text name="WLCurKeyTimeText"> -		Heure : +		H. :  	</text>  	<time name="time" value="6h"/>  	<check_box label="Appliquer ce nouveau cycle du jour" name="make_default_cb"/> diff --git a/indra/newview/skins/default/xui/fr/floater_environment_settings.xml b/indra/newview/skins/default/xui/fr/floater_environment_settings.xml index 9ea47a3dd7..ea12749d27 100644 --- a/indra/newview/skins/default/xui/fr/floater_environment_settings.xml +++ b/indra/newview/skins/default/xui/fr/floater_environment_settings.xml @@ -18,7 +18,7 @@  			<combo_box.item label="-Effectuer une sélection-" name="item0"/>  		</combo_box>  		<text name="sky_dayc_settings_title"> -			Ciel / Cycle du jour +			Ciel/Cycle du jour  		</text>  		<radio_group name="sky_dayc_settings_radio_group">  			<radio_item label="Ciel fixe" name="my_sky_settings"/> diff --git a/indra/newview/skins/default/xui/fr/floater_god_tools.xml b/indra/newview/skins/default/xui/fr/floater_god_tools.xml index e4c53d866c..0d21a8af32 100644 --- a/indra/newview/skins/default/xui/fr/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/fr/floater_god_tools.xml @@ -71,8 +71,8 @@  			<button label="Supprimer tous les objets scriptés de la cible sur les terrains des autres" label_selected="Supprimer tous les objets scriptés de la cible sur les terrains des autres" name="Delete Target's Scripted Objects On Others Land" tool_tip="Supprimer tous les objets scriptés appartenant à la cible sur les terrains ne lui appartenant pas. Les objets non copiables seront renvoyés."/>  			<button label="Supprimer les objets scriptés de la cible sur *tous* les terrains" label_selected="Supprimer les objets scriptés de la cible sur *tous* les terrains" name="Delete Target's Scripted Objects On *Any* Land" tool_tip="Supprimer les objets scriptés appartenant à la cible dans cette région. Les objets non copiables seront renvoyés."/>  			<button label="Supprimer *tous* les objets de la cible" label_selected="Supprimer *tous* les objets de la cible" name="Delete *ALL* Of Target's Objects" tool_tip="Supprimer tous les objets appartenant à la cible dans cette région. Les objets non copiables seront renvoyés."/> -			<button label="Afficher les collisions les plus consommatrices" label_selected="Afficher les collisions les plus consommatrices" name="Get Top Colliders" tool_tip="Dresse une liste des objets avec les callbacks les plus fréquents. " width="300"/> -			<button label="Afficher les objets scriptés les plus consommateurs" label_selected="Afficher les objets scriptés les plus consommateurs" name="Get Top Scripts" tool_tip="Dresse une liste des objets qui passent le plus de temps à exécuter des scripts." width="300"/> +			<button label="Collisions les plus consommatrices" label_selected="Collisions les plus consommatrices" name="Get Top Colliders" tool_tip="Liste des objets avec les callbacks les plus fréquents. " width="300"/> +			<button label="Scripts les plus consommateurs" label_selected="Scripts les plus consommateurs" name="Get Top Scripts" tool_tip="Liste des objets passant le plus de temps à exécuter des scripts." width="300"/>  			<button label="Résumé des scripts" label_selected="Résumé des scripts" name="Scripts digest" tool_tip="Dresse une liste des scripts et de leurs occurrences." width="300"/>  		</panel>  		<panel label="Requête" name="request"> diff --git a/indra/newview/skins/default/xui/fr/floater_land_holdings.xml b/indra/newview/skins/default/xui/fr/floater_land_holdings.xml index 10fe132623..ff728e3aaa 100644 --- a/indra/newview/skins/default/xui/fr/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/fr/floater_land_holdings.xml @@ -7,7 +7,7 @@  		<column label="Surface" name="area"/>  		<column label="" name="hidden"/>  	</scroll_list> -	<button label="Téléporter" label_selected="Téléporter" name="Teleport" tool_tip="Téléportez-vous au milieu de ce terrain."/> +	<button label="Téléportation" label_selected="Téléportation" name="Teleport" tool_tip="Téléportez-vous au milieu de ce terrain."/>  	<button label="Carte" label_selected="Carte" name="Show on Map" tool_tip="Afficher ce terrain sur la carte du monde"/>  	<text name="contrib_label">  		Vos contributions : diff --git a/indra/newview/skins/default/xui/fr/floater_preview_animation.xml b/indra/newview/skins/default/xui/fr/floater_preview_animation.xml index f2cb1d5e70..6488089c06 100644 --- a/indra/newview/skins/default/xui/fr/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/fr/floater_preview_animation.xml @@ -6,6 +6,6 @@  	<text name="desc txt">  		Description :  	</text> -	<button label="Exécuter dans Second Life" label_selected="Arrêter" name="Inworld" tool_tip="Lire cette animation de façon à ce que les autres la voient."/> +	<button label="Exécuter dans SL" label_selected="Arrêter" name="Inworld" tool_tip="Lire cette animation de façon à ce que les autres la voient dans Second Life."/>  	<button label="Exécuter localement" label_selected="Arrêter" name="Locally" tool_tip="Lire cette animation de façon à ce que vous soyez la seule personne à la voir."/>  </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_tools.xml b/indra/newview/skins/default/xui/fr/floater_tools.xml index e21c6f4c08..9643c51fb3 100644 --- a/indra/newview/skins/default/xui/fr/floater_tools.xml +++ b/indra/newview/skins/default/xui/fr/floater_tools.xml @@ -99,7 +99,7 @@  	<button label="" label_selected="" name="ToolRing" tool_tip="Anneau"/>  	<button label="" label_selected="" name="ToolTree" tool_tip="Arbre"/>  	<button label="" label_selected="" name="ToolGrass" tool_tip="Herbe"/> -	<check_box label="Maintenir l'outil sélectionné" name="checkbox sticky"/> +	<check_box label="Maintenir l'outil sélect." name="checkbox sticky"/>  	<check_box label="Copier la sélection" name="checkbox copy selection"/>  	<check_box initial_value="true" label="Centrer" name="checkbox copy centers"/>  	<check_box label="Pivoter" name="checkbox copy rotates"/> diff --git a/indra/newview/skins/default/xui/fr/floater_top_objects.xml b/indra/newview/skins/default/xui/fr/floater_top_objects.xml index 42352e7c1e..b40d585310 100644 --- a/indra/newview/skins/default/xui/fr/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/fr/floater_top_objects.xml @@ -1,16 +1,16 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <floater name="top_objects" title="Objets les plus utilisés">  	<floater.string name="top_scripts_title"> -		Scripts principaux +		Scripts les plus consommateurs  	</floater.string>  	<floater.string name="top_scripts_text">  		[COUNT] scripts prenant un total de [TIME] ms  	</floater.string>  	<floater.string name="scripts_score_label"> -		Heure +		Temps  	</floater.string>  	<floater.string name="scripts_mono_time_label"> -		Heure Mono +		Temps Mono  	</floater.string>  	<floater.string name="top_colliders_title">  		Collisions les plus consommatrices @@ -32,8 +32,8 @@  		<scroll_list.columns label="Nom" name="name"/>  		<scroll_list.columns label="Propriétaire" name="owner"/>  		<scroll_list.columns label="Lieu" name="location"/> -		<scroll_list.columns label="Heure" name="time"/> -		<scroll_list.columns label="Heure Mono" name="mono_time"/> +		<scroll_list.columns label="Temps" name="time"/> +		<scroll_list.columns label="Temps Mono" name="mono_time"/>  		<scroll_list.columns label="URL" name="URLs"/>  	</scroll_list>  	<text name="id_text"> @@ -43,7 +43,7 @@  	<text name="obj_name_text">  		Nom :  	</text> -	<button label="Filtre" name="filter_object_btn"/> +	<button label="Filtrer" name="filter_object_btn"/>  	<text name="owner_name_text">  		Propriétaire :  	</text> diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml index 2a26ed7a70..346b6ec2c7 100644 --- a/indra/newview/skins/default/xui/fr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml @@ -8,7 +8,7 @@  		<menu_item_call label="Nouvelle fenêtre d'inventaire" name="NewInventoryWindow"/>  		<menu_item_call label="Endroits..." name="Places"/>  		<menu_item_call label="Favoris..." name="Picks"/> -		<menu_item_call label="Paramètres de la caméra..." name="Camera Controls"/> +		<menu_item_call label="Caméra..." name="Camera Controls"/>  		<menu label="Déplacement" name="Movement">  			<menu_item_call label="M'asseoir" name="Sit Down Here"/>  			<menu_item_check label="Voler" name="Fly"/> @@ -171,7 +171,7 @@  		</menu>  		<menu label="Surbrillance et visibilité" name="Highlighting and Visibility">  			<menu_item_check label="Balise animée" name="Cheesy Beacon"/> -			<menu_item_check label="Cacher les particules" name="Hide Particles"/> +			<menu_item_check label="Masquer les particules" name="Hide Particles"/>  			<menu_item_check label="Masquer la sélection" name="Hide Selected"/>  			<menu_item_check label="Mettre la transparence en surbrillance" name="Highlight Transparent"/>  			<menu_item_check label="Afficher les éléments HUD" name="Show HUD Attachments"/> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index 0cdfc61e8e..729c06b50f 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -1314,7 +1314,7 @@ Dépasse la limite fixée à [MAX_AGENTS] [LIST_TYPE] de [NUM_EXCESS].  Veuillez choisir un objet à vendre et réessayer.  	</notification>  	<notification name="FinishedRawDownload"> -		Chargement du fichier de terrain raw effectué vers : +		Téléchargement du fichier de terrain raw effectué vers :  [DOWNLOAD_PATH].  	</notification>  	<notification name="DownloadWindowsMandatory"> diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_move.xml b/indra/newview/skins/default/xui/fr/panel_preferences_move.xml index 94d7322b22..80aed90a2d 100644 --- a/indra/newview/skins/default/xui/fr/panel_preferences_move.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_move.xml @@ -28,7 +28,7 @@  		<combo_box.item label="Déplacement vers le clic" name="1"/>  	</combo_box>  	<text name="double_click_action_lbl"> -		Double-clic sur le terrain : +		Double clic sur le terrain :  	</text>  	<combo_box name="double_click_action_combo">  		<combo_box.item label="Aucune action" name="0"/> diff --git a/indra/newview/skins/default/xui/fr/panel_region_debug.xml b/indra/newview/skins/default/xui/fr/panel_region_debug.xml index 733c3f9a22..6ea4b60072 100644 --- a/indra/newview/skins/default/xui/fr/panel_region_debug.xml +++ b/indra/newview/skins/default/xui/fr/panel_region_debug.xml @@ -30,9 +30,9 @@  	<check_box label="Sur le terrain d'un autre résident" name="return_other_land" tool_tip="Ne renvoyer que les objets se trouvant sur le terrain de quelqu'un d'autre"/>  	<check_box label="Dans toutes les régions de ce domaine" name="return_estate_wide" tool_tip="Renvoyer les objets dans toutes les régions qui constituent ce domaine"/>  	<button label="Renvoyer" name="return_btn"/> -	<button label="Afficher les collisions les plus consommatrices..." name="top_colliders_btn" tool_tip="Liste des objets avec le plus de collisions potentielles" width="320"/> +	<button label="Collisions les plus consommatrices" name="top_colliders_btn" tool_tip="Liste des objets avec le plus de collisions potentielles" width="320"/>  	<button label="?" left="337" name="top_colliders_help"/> -	<button label="Afficher les objets scriptés les plus consommateurs..." name="top_scripts_btn" tool_tip="Liste des objets qui passent le plus de temps à exécuter des scripts" width="320"/> +	<button label="Scripts les plus consommateurs" name="top_scripts_btn" tool_tip="Liste des objets passant le plus de temps à exécuter des scripts" width="320"/>  	<button label="?" left="337" name="top_scripts_help"/>  	<button label="Redémarrer la région" name="restart_btn" tool_tip="Redémarrer la région au bout de 2 minutes" width="160"/>  	<button label="?" left="177" name="restart_help"/> diff --git a/indra/newview/skins/default/xui/fr/panel_region_environment.xml b/indra/newview/skins/default/xui/fr/panel_region_environment.xml index d18503db86..085a308786 100644 --- a/indra/newview/skins/default/xui/fr/panel_region_environment.xml +++ b/indra/newview/skins/default/xui/fr/panel_region_environment.xml @@ -15,7 +15,7 @@  			<combo_box.item label="-Effectuer une sélection-" name="item0"/>  		</combo_box>  		<text name="sky_dayc_settings_title"> -			Ciel / Cycle du jour +			Ciel/Cycle du jour  		</text>  		<radio_group name="sky_dayc_settings_radio_group">  			<radio_item label="Ciel fixe" name="my_sky_settings"/> diff --git a/indra/newview/skins/default/xui/fr/panel_region_general.xml b/indra/newview/skins/default/xui/fr/panel_region_general.xml index b5795bebe2..234d316069 100644 --- a/indra/newview/skins/default/xui/fr/panel_region_general.xml +++ b/indra/newview/skins/default/xui/fr/panel_region_general.xml @@ -22,7 +22,7 @@  	<check_box label="Interdire le vol" name="block_fly_check"/>  	<check_box label="Autoriser les dégâts" name="allow_damage_check"/>  	<check_box label="Interdire les bousculades" name="restrict_pushobject"/> -	<check_box label="Autoriser la revente" name="allow_land_resell_check"/> +	<check_box label="Autoriser la revente de terrain" name="allow_land_resell_check"/>  	<check_box label="Autoriser la fusion/division" name="allow_parcel_changes_check"/>  	<check_box label="Ne pas afficher dans la recherche" name="block_parcel_search_check" tool_tip="Afficher cette région et ses parcelles dans les résultats de recherche"/>  	<check_box label="Autoriser les objets de maillage" name="mesh_rez_enabled_check" tool_tip="Laisser les gens rezzer des objets de maillage dans cette région."/> diff --git a/indra/newview/skins/default/xui/fr/panel_region_terrain.xml b/indra/newview/skins/default/xui/fr/panel_region_terrain.xml index d7e321d06d..97f486d3a3 100644 --- a/indra/newview/skins/default/xui/fr/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/fr/panel_region_terrain.xml @@ -55,8 +55,8 @@ du terrain" name="terrain_lower_spin"/>  	<spinner label="Bas" name="height_start_spin_2"/>  	<spinner label="Haut" name="height_range_spin_0"/>  	<spinner label="Haut" name="height_range_spin_2"/> -	<button label="Télécharger le terrain au format RAW..." name="download_raw_btn" tool_tip="Réservé aux propriétaires de domaine, pas aux gérants" width="230"/> -	<button label="Charger le terrain au format RAW..." name="upload_raw_btn" tool_tip="Réservé aux propriétaires de domaine, pas aux gérants" width="230"/> +	<button label="Télécharger le terrain en RAW..." name="download_raw_btn" tool_tip="Réservé aux propriétaires de domaine, pas aux gérants" width="230"/> +	<button label="Charger un terrain en RAW..." name="upload_raw_btn" tool_tip="Réservé aux propriétaires de domaine, pas aux gérants" width="230"/>  	<button label="Figer le terrain" name="bake_terrain_btn" tool_tip="Définir le terrain actuel comme point central pour les limites d'élévation/abaissement"/>  	<button label="Appliquer" name="apply_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml index 4454d2475e..f40bcec908 100644 --- a/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel name="panel_snapshot_inventory">  	<text name="title"> -		Enregistrer dans mon inventaire +		Enregistrer dans l'inventaire  	</text>  	<text name="hint_lbl">  		L'enregistrement d'une image dans votre inventaire coûte [UPLOAD_COST] L$. Pour enregistrer votre image sous forme de texture, sélectionnez l'un des formats carrés. diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_local.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_local.xml index 41264521fd..48ccacb374 100644 --- a/indra/newview/skins/default/xui/fr/panel_snapshot_local.xml +++ b/indra/newview/skins/default/xui/fr/panel_snapshot_local.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel name="panel_snapshot_local">  	<text name="title"> -		Enregistrer sur mon ordinateur +		Enregistrer sur l'ordinateur  	</text>  	<combo_box label="Résolution" name="local_size_combo">  		<combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/> @@ -25,7 +25,7 @@  				<combo_box.item label="JPEG" name="JPEG"/>  				<combo_box.item label="BMP (sans perte)" name="BMP"/>  			</combo_box> -			<slider label="Qualité de l'image" name="image_quality_slider"/> +			<slider label="Qualité d'image" name="image_quality_slider"/>  			<text name="image_quality_level">  				([QLVL])  			</text> diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml index db3fcbeac9..befe1b3bc6 100644 --- a/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml +++ b/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml @@ -2,6 +2,6 @@  <panel name="panel_snapshot_options">  	<button label="Publier sur le flux de mon profil" name="save_to_profile_btn"/>  	<button label="Envoyer par e-mail" name="save_to_email_btn"/> -	<button label="Enregistrer dans mon inventaire ([AMOUNT] L$)" name="save_to_inventory_btn"/> -	<button label="Enregistrer sur mon ordinateur" name="save_to_computer_btn"/> +	<button label="Enreg. dans l'inventaire ([AMOUNT] L$)" name="save_to_inventory_btn"/> +	<button label="Enreg. sur l'ordinateur" name="save_to_computer_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml index bb23b52850..82a4815144 100644 --- a/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml @@ -10,7 +10,7 @@  		Envoi en cours...  	</string>  	<text name="title"> -		Envoyer par e-mail +		E-mail  	</text>  	<button label="Message" name="message_btn"/>  	<button label="Paramètres" name="settings_btn"/>  | 
