diff options
| author | Monroe Linden <monroe@lindenlab.com> | 2010-08-13 14:01:51 -0700 | 
|---|---|---|
| committer | Monroe Linden <monroe@lindenlab.com> | 2010-08-13 14:01:51 -0700 | 
| commit | 1dd490ff88e7ee54b689e01529ffb88a3fc7491b (patch) | |
| tree | 487ab551a0fc567bd94672c4a7e06625cc8b99ec /indra | |
| parent | 7f085551431aa912a4a2be28e2b714d12f723809 (diff) | |
| parent | 4ef75f35c195a4e2657a0e01d6b92cd40e6779f5 (diff) | |
Automated merge with ssh://hg.lindenlab.com/dessie/viewer-public
Diffstat (limited to 'indra')
70 files changed, 1710 insertions, 579 deletions
| diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h index 1a5678dde1..e0565204d4 100644 --- a/indra/llcommon/stdenums.h +++ b/indra/llcommon/stdenums.h @@ -119,8 +119,8 @@ enum EObjectPropertiesExtraID  enum EAddPosition  {  	ADD_TOP, -	ADD_SORTED, -	ADD_BOTTOM +	ADD_BOTTOM, +	ADD_DEFAULT  };  enum LLGroupChange diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index d6c062fc5e..849318ccee 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -983,37 +983,43 @@ LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)  //static  LLFontGL* LLFontGL::getFontMonospace()  { -	return getFont(LLFontDescriptor("Monospace","Monospace",0)); +	static LLFontGL* fontp = getFont(LLFontDescriptor("Monospace","Monospace",0)); +	return fontp;  }  //static  LLFontGL* LLFontGL::getFontSansSerifSmall()  { -	return getFont(LLFontDescriptor("SansSerif","Small",0)); +	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",0)); +	return fontp;  }  //static  LLFontGL* LLFontGL::getFontSansSerif()  { -	return getFont(LLFontDescriptor("SansSerif","Medium",0)); +	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",0)); +	return fontp;  }  //static  LLFontGL* LLFontGL::getFontSansSerifBig()  { -	return getFont(LLFontDescriptor("SansSerif","Large",0)); +	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0)); +	return fontp;  }  //static   LLFontGL* LLFontGL::getFontSansSerifHuge()  { -	return getFont(LLFontDescriptor("SansSerif","Huge",0)); +	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0)); +	return fontp;  }  //static   LLFontGL* LLFontGL::getFontSansSerifBold()  { -	return getFont(LLFontDescriptor("SansSerif","Medium",BOLD)); +	static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",BOLD)); +	return fontp;  }  //static diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 64238b2008..eb2c54198d 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -901,7 +901,7 @@ LLVector3 LLRender::getUITranslation()  {  	if (mUIOffset.empty())  	{ -		llerrs << "UI offset stack empty." << llendl; +		return LLVector3::zero;  	}  	return mUIOffset.back();  } @@ -910,7 +910,7 @@ LLVector3 LLRender::getUIScale()  {  	if (mUIScale.empty())  	{ -		llerrs << "UI scale stack empty." << llendl; +		return LLVector3(1.f, 1.f, 1.f);  	}  	return mUIScale.back();  } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index bb43c19c2c..d356f061f9 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -543,23 +543,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r  			setNeedsSort();  			break; -		case ADD_SORTED: -			{ -				// sort by column 0, in ascending order -				std::vector<sort_column_t> single_sort_column; -				single_sort_column.push_back(std::make_pair(0, TRUE)); - -				mItemList.push_back(item); -				std::stable_sort( -					mItemList.begin(),  -					mItemList.end(),  -					SortScrollListItem(single_sort_column,mSortCallback)); -				 -				// ADD_SORTED just sorts by first column... -				// this might not match user sort criteria, so flag list as being in unsorted state -				setNeedsSort(); -				break; -			}	 +		case ADD_DEFAULT:  		case ADD_BOTTOM:  			mItemList.push_back(item);  			setNeedsSort(); @@ -2770,9 +2754,10 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name)  	return NULL;  } - +LLFastTimer::DeclareTimer FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item");  LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)  { +	LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);  	LLScrollListItem::Params item_params;  	LLParamSDParser::instance().readSD(element, item_params);  	item_params.userdata = userdata; @@ -2781,12 +2766,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition  LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos)  { +	LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);  	LLScrollListItem *new_item = new LLScrollListItem(item_p);  	return addRow(new_item, item_p, pos);  }  LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos)  { +	LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);  	if (!item_p.validateBlock() || !new_item) return NULL;  	new_item->setNumColumns(mColumns.size()); diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 4bb45a3065..7d37127584 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -43,33 +43,16 @@ LLParamSDParser::LLParamSDParser()  {  	using boost::bind; -	registerParserFuncs<S32>(bind(&LLParamSDParser::readTypedValue<S32>, this, _1, &LLSD::asInteger), -							bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2)); -	registerParserFuncs<U32>(bind(&LLParamSDParser::readTypedValue<U32>, this, _1, &LLSD::asInteger), -							bind(&LLParamSDParser::writeU32Param, this, _1, _2)); -	registerParserFuncs<F32>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asReal), -							bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2)); -	registerParserFuncs<F64>(bind(&LLParamSDParser::readTypedValue<F64>, this, _1, &LLSD::asReal), -							bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2)); -	registerParserFuncs<bool>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asBoolean), -							bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2)); -	registerParserFuncs<std::string>(bind(&LLParamSDParser::readTypedValue<std::string>, this, _1, &LLSD::asString), -							bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2)); -	registerParserFuncs<LLUUID>(bind(&LLParamSDParser::readTypedValue<LLUUID>, this, _1, &LLSD::asUUID), -							bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2)); -	registerParserFuncs<LLDate>(bind(&LLParamSDParser::readTypedValue<LLDate>, this, _1, &LLSD::asDate), -							bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2)); -	registerParserFuncs<LLURI>(bind(&LLParamSDParser::readTypedValue<LLURI>, this, _1, &LLSD::asURI), -							bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2)); -	registerParserFuncs<LLSD>(bind(&LLParamSDParser::readSDParam, this, _1), -							bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2)); -} - -bool LLParamSDParser::readSDParam(void* value_ptr) -{ -	if (!mCurReadSD) return false; -	*((LLSD*)value_ptr) = *mCurReadSD; -	return true; +	registerParserFuncs<S32>(readS32, bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2)); +	registerParserFuncs<U32>(readU32, bind(&LLParamSDParser::writeU32Param, this, _1, _2)); +	registerParserFuncs<F32>(readF32, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2)); +	registerParserFuncs<F64>(readF64, bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2)); +	registerParserFuncs<bool>(readBool, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2)); +	registerParserFuncs<std::string>(readString, bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2)); +	registerParserFuncs<LLUUID>(readUUID, bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2)); +	registerParserFuncs<LLDate>(readDate, bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2)); +	registerParserFuncs<LLURI>(readURI, bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2)); +	registerParserFuncs<LLSD>(readSD, bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2));  }  // special case handling of U32 due to ambiguous LLSD::assign overload @@ -148,3 +131,82 @@ LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack)  	return mWriteSD;  } +bool LLParamSDParser::readS32(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +    *((S32*)val_ptr) = self.mCurReadSD->asInteger(); +    return true; +} + +bool LLParamSDParser::readU32(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +    *((U32*)val_ptr) = self.mCurReadSD->asInteger(); +    return true; +} + +bool LLParamSDParser::readF32(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +    *((F32*)val_ptr) = self.mCurReadSD->asReal(); +    return true; +} + +bool LLParamSDParser::readF64(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +    *((F64*)val_ptr) = self.mCurReadSD->asReal(); +    return true; +} + +bool LLParamSDParser::readBool(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +    *((bool*)val_ptr) = self.mCurReadSD->asBoolean(); +    return true; +} + +bool LLParamSDParser::readString(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +	*((std::string*)val_ptr) = self.mCurReadSD->asString(); +    return true; +} + +bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +	*((LLUUID*)val_ptr) = self.mCurReadSD->asUUID(); +    return true; +} + +bool LLParamSDParser::readDate(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +	*((LLDate*)val_ptr) = self.mCurReadSD->asDate(); +    return true; +} + +bool LLParamSDParser::readURI(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +	*((LLURI*)val_ptr) = self.mCurReadSD->asURI(); +    return true; +} + +bool LLParamSDParser::readSD(Parser& parser, void* val_ptr) +{ +	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); + +	*((LLSD*)val_ptr) = *self.mCurReadSD; +    return true; +} diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h index 12f28f876f..71b0a45630 100644 --- a/indra/llui/llsdparam.h +++ b/indra/llui/llsdparam.h @@ -79,9 +79,19 @@ private:  	LLSD* getSDWriteNode(const parser_t::name_stack_t& name_stack); -	bool readSDParam(void* value_ptr);  	bool writeU32Param(const void* value_ptr, const parser_t::name_stack_t& name_stack); +	static bool readS32(Parser& parser, void* val_ptr); +	static bool readU32(Parser& parser, void* val_ptr); +	static bool readF32(Parser& parser, void* val_ptr); +	static bool readF64(Parser& parser, void* val_ptr); +	static bool readBool(Parser& parser, void* val_ptr); +	static bool readString(Parser& parser, void* val_ptr); +	static bool readUUID(Parser& parser, void* val_ptr); +	static bool readDate(Parser& parser, void* val_ptr); +	static bool readURI(Parser& parser, void* val_ptr); +	static bool readSD(Parser& parser, void* val_ptr); +  	Parser::name_stack_t	mNameStack;  	const LLSD*				mCurReadSD;  	LLSD*					mWriteSD; diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index a46d961709..c5bd6c7fce 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -99,10 +99,11 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa  	std::string filename = std::string("widgets") + gDirUtilp->getDirDelimiter() + widget_tag + ".xml";  	LLXMLNodePtr root_node; -	if (LLUICtrlFactory::getLayeredXMLNode(filename, root_node)) +	std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), filename); +	if (!full_filename.empty())  	{ -		LLUICtrlFactory::instance().pushFileName(filename); -		LLXUIParser::instance().readXUI(root_node, block, filename); +		LLUICtrlFactory::instance().pushFileName(full_filename); +		LLSimpleXUIParser::instance().readXUI(full_filename, block);  		LLUICtrlFactory::instance().popFileName();  	}  } diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index ac9e71665f..e343df0063 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -40,7 +40,7 @@ LLFastTimer::DeclareTimer FTM_UI_STRING("UI String");  LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args)  :	mOrig(instring), -	mArgs(args) +	mArgs(new LLStringUtil::format_map_t(args))  {  	dirty();  } @@ -54,7 +54,7 @@ void LLUIString::assign(const std::string& s)  void LLUIString::setArgList(const LLStringUtil::format_map_t& args)  { -	mArgs = args; +	getArgs() = args;  	dirty();  } @@ -74,7 +74,7 @@ void LLUIString::setArgs(const LLSD& sd)  void LLUIString::setArg(const std::string& key, const std::string& replacement)  { -	mArgs[key] = replacement; +	getArgs()[key] = replacement;  	dirty();  } @@ -135,14 +135,14 @@ void LLUIString::updateResult() const  	mResult = mOrig;  	// get the defailt args + local args -	if (mArgs.empty()) +	if (!mArgs || mArgs->empty())  	{  		LLStringUtil::format(mResult, LLTrans::getDefaultArgs());  	}  	else  	{  		LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs(); -		combined_args.insert(mArgs.begin(), mArgs.end()); +		combined_args.insert(mArgs->begin(), mArgs->end());  		LLStringUtil::format(mResult, combined_args);  	}  } @@ -153,3 +153,12 @@ void LLUIString::updateWResult() const  	mWResult = utf8str_to_wstring(getUpdatedResult());  } + +LLStringUtil::format_map_t& LLUIString::getArgs() +{ +	if (!mArgs) +	{ +		mArgs = new LLStringUtil::format_map_t; +	} +	return *mArgs; +} diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h index 32cfc0d9cd..3f91856e26 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -64,9 +64,9 @@ class LLUIString  public:  	// These methods all perform appropriate argument substitution  	// and modify mOrig where appropriate -        LLUIString() : mNeedsResult(false), mNeedsWResult(false) {} +        LLUIString() : mArgs(NULL), mNeedsResult(false), mNeedsWResult(false) {}  	LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args); -	LLUIString(const std::string& instring) { assign(instring); } +	LLUIString(const std::string& instring) : mArgs(NULL) { assign(instring); }  	void assign(const std::string& instring);  	LLUIString& operator=(const std::string& s) { assign(s); return *this; } @@ -86,7 +86,7 @@ public:  	S32 length() const { return getUpdatedWResult().size(); }  	void clear(); -	void clearArgs() { mArgs.clear(); } +	void clearArgs() { if (mArgs) mArgs->clear(); }  	// These utility functions are included for text editing.  	// They do not affect mOrig and do not perform argument substitution @@ -105,11 +105,12 @@ private:  	// do actual work of updating strings (non-inlined)  	void updateResult() const;  	void updateWResult() const; +	LLStringUtil::format_map_t& getArgs();  	std::string mOrig;  	mutable std::string mResult;  	mutable LLWString mWResult; // for displaying -	LLStringUtil::format_map_t mArgs; +	LLStringUtil::format_map_t* mArgs;  	// controls lazy evaluation  	mutable bool	mNeedsResult; diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index b645c4be7c..9890bacea4 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -40,6 +40,7 @@ f * @file llinitparam.h  #include <boost/function.hpp>  #include <boost/bind.hpp>  #include <boost/type_traits/is_convertible.hpp> +#include <boost/unordered_map.hpp>  #include "llregistry.h"  #include "llmemory.h" @@ -202,7 +203,7 @@ namespace LLInitParam  		typedef std::pair<name_stack_t::const_iterator, name_stack_t::const_iterator>	name_stack_range_t;  		typedef std::vector<std::string>							possible_values_t; -		typedef boost::function<bool (void*)>															parser_read_func_t; +		typedef bool (*parser_read_func_t)(Parser& parser, void* output);  		typedef boost::function<bool (const void*, const name_stack_t&)>								parser_write_func_t;  		typedef boost::function<void (const name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t; @@ -221,7 +222,7 @@ namespace LLInitParam  		    parser_read_func_map_t::iterator found_it = mParserReadFuncs.find(&typeid(T));  		    if (found_it != mParserReadFuncs.end())  		    { -			    return found_it->second((void*)¶m); +			    return found_it->second(*this, (void*)¶m);  		    }  		    return false;  	    } @@ -386,7 +387,7 @@ namespace LLInitParam  		void aggregateBlockData(BlockDescriptor& src_block_data);  	public: -		typedef std::map<const std::string, ParamDescriptor*> param_map_t; // references param descriptors stored in mAllParams +		typedef boost::unordered_map<const std::string, ParamDescriptor*> param_map_t; // references param descriptors stored in mAllParams  		typedef std::vector<ParamDescriptor*> param_list_t;   		typedef std::list<ParamDescriptor> all_params_list_t;// references param descriptors stored in mAllParams diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index dbc20a5a1e..d856efb008 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -35,11 +35,16 @@  #include "llxuiparser.h"  #include "llxmlnode.h" +#include "expat/expat.h"  #include <fstream>  #include <boost/tokenizer.hpp> +//#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/classic_core.hpp>  #include "lluicolor.h" +using namespace BOOST_SPIRIT_CLASSIC_NS; +  const S32 MAX_STRING_ATTRIBUTE_SIZE = 40;  // @@ -370,34 +375,20 @@ LLXUIParser::LLXUIParser()  :	mLastWriteGeneration(-1),  	mCurReadDepth(0)  { -	registerParserFuncs<bool>(boost::bind(&LLXUIParser::readBoolValue, this, _1), -								boost::bind(&LLXUIParser::writeBoolValue, this, _1, _2)); -	registerParserFuncs<std::string>(boost::bind(&LLXUIParser::readStringValue, this, _1), -								boost::bind(&LLXUIParser::writeStringValue, this, _1, _2)); -	registerParserFuncs<U8>(boost::bind(&LLXUIParser::readU8Value, this, _1), -								boost::bind(&LLXUIParser::writeU8Value, this, _1, _2)); -	registerParserFuncs<S8>(boost::bind(&LLXUIParser::readS8Value, this, _1), -								boost::bind(&LLXUIParser::writeS8Value, this, _1, _2)); -	registerParserFuncs<U16>(boost::bind(&LLXUIParser::readU16Value, this, _1), -								boost::bind(&LLXUIParser::writeU16Value, this, _1, _2)); -	registerParserFuncs<S16>(boost::bind(&LLXUIParser::readS16Value, this, _1), -								boost::bind(&LLXUIParser::writeS16Value, this, _1, _2)); -	registerParserFuncs<U32>(boost::bind(&LLXUIParser::readU32Value, this, _1), -								boost::bind(&LLXUIParser::writeU32Value, this, _1, _2)); -	registerParserFuncs<S32>(boost::bind(&LLXUIParser::readS32Value, this, _1), -								boost::bind(&LLXUIParser::writeS32Value, this, _1, _2)); -	registerParserFuncs<F32>(boost::bind(&LLXUIParser::readF32Value, this, _1), -								boost::bind(&LLXUIParser::writeF32Value, this, _1, _2)); -	registerParserFuncs<F64>(boost::bind(&LLXUIParser::readF64Value, this, _1), -								boost::bind(&LLXUIParser::writeF64Value, this, _1, _2)); -	registerParserFuncs<LLColor4>(boost::bind(&LLXUIParser::readColor4Value, this, _1), -								boost::bind(&LLXUIParser::writeColor4Value, this, _1, _2)); -	registerParserFuncs<LLUIColor>(boost::bind(&LLXUIParser::readUIColorValue, this, _1), -								boost::bind(&LLXUIParser::writeUIColorValue, this, _1, _2)); -	registerParserFuncs<LLUUID>(boost::bind(&LLXUIParser::readUUIDValue, this, _1), -								boost::bind(&LLXUIParser::writeUUIDValue, this, _1, _2)); -	registerParserFuncs<LLSD>(boost::bind(&LLXUIParser::readSDValue, this, _1), -								boost::bind(&LLXUIParser::writeSDValue, this, _1, _2)); +	registerParserFuncs<bool>(readBoolValue, boost::bind(&LLXUIParser::writeBoolValue, this, _1, _2)); +	registerParserFuncs<std::string>(readStringValue, boost::bind(&LLXUIParser::writeStringValue, this, _1, _2)); +	registerParserFuncs<U8>(readU8Value, boost::bind(&LLXUIParser::writeU8Value, this, _1, _2)); +	registerParserFuncs<S8>(readS8Value, boost::bind(&LLXUIParser::writeS8Value, this, _1, _2)); +	registerParserFuncs<U16>(readU16Value, boost::bind(&LLXUIParser::writeU16Value, this, _1, _2)); +	registerParserFuncs<S16>(readS16Value, boost::bind(&LLXUIParser::writeS16Value, this, _1, _2)); +	registerParserFuncs<U32>(readU32Value, boost::bind(&LLXUIParser::writeU32Value, this, _1, _2)); +	registerParserFuncs<S32>(readS32Value, boost::bind(&LLXUIParser::writeS32Value, this, _1, _2)); +	registerParserFuncs<F32>(readF32Value, boost::bind(&LLXUIParser::writeF32Value, this, _1, _2)); +	registerParserFuncs<F64>(readF64Value, boost::bind(&LLXUIParser::writeF64Value, this, _1, _2)); +	registerParserFuncs<LLColor4>(readColor4Value, boost::bind(&LLXUIParser::writeColor4Value, this, _1, _2)); +	registerParserFuncs<LLUIColor>(readUIColorValue, boost::bind(&LLXUIParser::writeUIColorValue, this, _1, _2)); +	registerParserFuncs<LLUUID>(readUUIDValue, boost::bind(&LLXUIParser::writeUUIDValue, this, _1, _2)); +	registerParserFuncs<LLSD>(readSDValue, boost::bind(&LLXUIParser::writeSDValue, this, _1, _2));  }  static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing"); @@ -621,10 +612,11 @@ LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack)  } -bool LLXUIParser::readBoolValue(void* val_ptr) +bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr)  {  	S32 value; -	bool success = mCurReadNode->getBoolValue(1, &value); +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	bool success = self.mCurReadNode->getBoolValue(1, &value);  	*((bool*)val_ptr) = (value != FALSE);  	return success;  } @@ -640,9 +632,10 @@ bool LLXUIParser::writeBoolValue(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readStringValue(void* val_ptr) +bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr)  { -	*((std::string*)val_ptr) = mCurReadNode->getSanitizedValue(); +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	*((std::string*)val_ptr) = self.mCurReadNode->getSanitizedValue();  	return true;  } @@ -677,9 +670,10 @@ bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stac  	return false;  } -bool LLXUIParser::readU8Value(void* val_ptr) +bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr)  { -	return mCurReadNode->getByteValue(1, (U8*)val_ptr); +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	return self.mCurReadNode->getByteValue(1, (U8*)val_ptr);  }  bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack) @@ -693,10 +687,11 @@ bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readS8Value(void* val_ptr) +bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr)  { +	LLXUIParser& self = static_cast<LLXUIParser&>(parser);  	S32 value; -	if(mCurReadNode->getIntValue(1, &value)) +	if(self.mCurReadNode->getIntValue(1, &value))  	{  		*((S8*)val_ptr) = value;  		return true; @@ -715,10 +710,11 @@ bool LLXUIParser::writeS8Value(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readU16Value(void* val_ptr) +bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr)  { +	LLXUIParser& self = static_cast<LLXUIParser&>(parser);  	U32 value; -	if(mCurReadNode->getUnsignedValue(1, &value)) +	if(self.mCurReadNode->getUnsignedValue(1, &value))  	{  		*((U16*)val_ptr) = value;  		return true; @@ -737,10 +733,11 @@ bool LLXUIParser::writeU16Value(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readS16Value(void* val_ptr) +bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr)  { +	LLXUIParser& self = static_cast<LLXUIParser&>(parser);  	S32 value; -	if(mCurReadNode->getIntValue(1, &value)) +	if(self.mCurReadNode->getIntValue(1, &value))  	{  		*((S16*)val_ptr) = value;  		return true; @@ -759,9 +756,10 @@ bool LLXUIParser::writeS16Value(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readU32Value(void* val_ptr) +bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr)  { -	return mCurReadNode->getUnsignedValue(1, (U32*)val_ptr); +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);  }  bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack) @@ -775,9 +773,10 @@ bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readS32Value(void* val_ptr) +bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr)  { -	return mCurReadNode->getIntValue(1, (S32*)val_ptr); +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	return self.mCurReadNode->getIntValue(1, (S32*)val_ptr);  }  bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack) @@ -791,9 +790,10 @@ bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readF32Value(void* val_ptr) +bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr)  { -	return mCurReadNode->getFloatValue(1, (F32*)val_ptr); +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr);  }  bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack) @@ -807,9 +807,10 @@ bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readF64Value(void* val_ptr) +bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr)  { -	return mCurReadNode->getDoubleValue(1, (F64*)val_ptr); +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr);  }  bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack) @@ -823,10 +824,11 @@ bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readColor4Value(void* val_ptr) +bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)  { +	LLXUIParser& self = static_cast<LLXUIParser&>(parser);  	LLColor4* colorp = (LLColor4*)val_ptr; -	if(mCurReadNode->getFloatValue(4, colorp->mV) >= 3) +	if(self.mCurReadNode->getFloatValue(4, colorp->mV) >= 3)  	{  		return true;  	} @@ -846,11 +848,12 @@ bool LLXUIParser::writeColor4Value(const void* val_ptr, const name_stack_t& stac  	return false;  } -bool LLXUIParser::readUIColorValue(void* val_ptr) +bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr)  { +	LLXUIParser& self = static_cast<LLXUIParser&>(parser);  	LLUIColor* param = (LLUIColor*)val_ptr;  	LLColor4 color; -	bool success =  mCurReadNode->getFloatValue(4, color.mV) >= 3; +	bool success =  self.mCurReadNode->getFloatValue(4, color.mV) >= 3;  	if (success)  	{  		param->set(color); @@ -874,11 +877,12 @@ bool LLXUIParser::writeUIColorValue(const void* val_ptr, const name_stack_t& sta  	return false;  } -bool LLXUIParser::readUUIDValue(void* val_ptr) +bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr)  { +	LLXUIParser& self = static_cast<LLXUIParser&>(parser);  	LLUUID temp_id;  	// LLUUID::set is destructive, so use temporary value -	if (temp_id.set(mCurReadNode->getSanitizedValue())) +	if (temp_id.set(self.mCurReadNode->getSanitizedValue()))  	{  		*(LLUUID*)(val_ptr) = temp_id;  		return true; @@ -897,9 +901,10 @@ bool LLXUIParser::writeUUIDValue(const void* val_ptr, const name_stack_t& stack)  	return false;  } -bool LLXUIParser::readSDValue(void* val_ptr) +bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr)  { -	*((LLSD*)val_ptr) = LLSD(mCurReadNode->getSanitizedValue()); +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	*((LLSD*)val_ptr) = LLSD(self.mCurReadNode->getSanitizedValue());  	return true;  } @@ -968,3 +973,411 @@ void LLXUIParser::parserError(const std::string& message)  	Parser::parserError(message);  #endif  } + + +// +// LLSimpleXUIParser +// + +struct ScopedFile +{ +	ScopedFile( const std::string& filename, const char* accessmode ) +	{ +		mFile = LLFile::fopen(filename, accessmode); +	} + +	~ScopedFile() +	{ +		fclose(mFile); +		mFile = NULL; +	} + +	S32 getRemainingBytes() +	{ +		if (!isOpen()) return 0; + +		S32 cur_pos = ftell(mFile); +		fseek(mFile, 0L, SEEK_END); +		S32 file_size = ftell(mFile); +		fseek(mFile, cur_pos, SEEK_SET); +		return file_size - cur_pos; +	} + +	bool isOpen() { return mFile != NULL; } + +	LLFILE* mFile; +}; + +LLSimpleXUIParser::LLSimpleXUIParser() +:	mLastWriteGeneration(-1), +	mCurReadDepth(0) +{ +	registerParserFuncs<bool>(readBoolValue, NULL); +	registerParserFuncs<std::string>(readStringValue, NULL); +	registerParserFuncs<U8>(readU8Value, NULL); +	registerParserFuncs<S8>(readS8Value, NULL); +	registerParserFuncs<U16>(readU16Value, NULL); +	registerParserFuncs<S16>(readS16Value, NULL); +	registerParserFuncs<U32>(readU32Value, NULL); +	registerParserFuncs<S32>(readS32Value, NULL); +	registerParserFuncs<F32>(readF32Value, NULL); +	registerParserFuncs<F64>(readF64Value, NULL); +	registerParserFuncs<LLColor4>(readColor4Value, NULL); +	registerParserFuncs<LLUIColor>(readUIColorValue, NULL); +	registerParserFuncs<LLUUID>(readUUIDValue, NULL); +	registerParserFuncs<LLSD>(readSDValue, NULL); +} + +LLSimpleXUIParser::~LLSimpleXUIParser() +{ +} + + +bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent) +{ +	LLFastTimer timer(FTM_PARSE_XUI); + +	mParser = XML_ParserCreate(NULL); +	XML_SetUserData(mParser, this); +	XML_SetElementHandler(			mParser,	startElementHandler, endElementHandler); +	XML_SetCharacterDataHandler(	mParser,	characterDataHandler); + +	mBlock = █ +	mNameStack.clear(); +	mCurFileName = filename; +	mCurReadDepth = 0; +	setParseSilently(silent); + +	ScopedFile file(filename, "rb"); +	if( !file.isOpen() ) +	{ +		LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL; +		return false; +	} + +	S32 bytes_read = 0; +	 +	S32 buffer_size = file.getRemainingBytes(); +	void* buffer = XML_GetBuffer(mParser, buffer_size); +	if( !buffer )  +	{ +		LL_WARNS("ReadXUI") << "Unable to allocate XML buffer while reading file " << filename << LL_ENDL; +		XML_ParserFree( mParser ); +		return false; +	} + +	bytes_read = (S32)fread(buffer, 1, buffer_size, file.mFile); +	if( bytes_read <= 0 ) +	{ +		LL_WARNS("ReadXUI") << "Error while reading file  " << filename << LL_ENDL; +		XML_ParserFree( mParser ); +		return false; +	} +	 +	if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) ) +	{ +		LL_WARNS("ReadXUI") << "Error while parsing file  " << filename << LL_ENDL; +		XML_ParserFree( mParser ); +		return false; +	} + +	XML_ParserFree( mParser ); +	return true; +} + +void LLSimpleXUIParser::startElementHandler(void *userData, const char *name, const char **atts) +{ +	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData); +	self->startElement(name, atts); +} + +void LLSimpleXUIParser::endElementHandler(void *userData, const char *name) +{ +	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData); +	self->endElement(name); +} + +void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int len) +{ +	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData); +	self->characterData(s, len); +} + +void LLSimpleXUIParser::startElement(const char *name, const char **atts) +{ +	typedef boost::tokenizer<boost::char_separator<char> > tokenizer; +	boost::char_separator<char> sep("."); + +	mCurReadDepth++; +	S32 num_tokens_pushed = 0; +	std::string child_name(name); + +	if (mCurReadDepth > 1) +	{ +		// for non "dotted" child nodes	check to see if child node maps to another widget type +		// and if not, treat as a child element of the current node +		// e.g. <button><rect left="10"/></button> will interpret <rect> as "button.rect" +		// since there is no widget named "rect" +		if (child_name.find(".") == std::string::npos)  +		{ +			mNameStack.push_back(std::make_pair(child_name, newParseGeneration())); +			num_tokens_pushed++; +			mScope.push_back(child_name); +		} +		else +		{ +			// parse out "dotted" name into individual tokens +			tokenizer name_tokens(child_name, sep); + +			tokenizer::iterator name_token_it = name_tokens.begin(); +			if(name_token_it == name_tokens.end())  +			{ +				return; +			} + +			// check for proper nesting +			if(!mScope.empty() && *name_token_it != mScope.back()) +			{ +				return; +			} + +			// now ignore first token +			++name_token_it;  + +			// copy remaining tokens on to our running token list +			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push) +			{ +				mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration())); +				num_tokens_pushed++; +			} +			mScope.push_back(mNameStack.back().first); +		} +	} +	else +	{ +		mScope.push_back(child_name); +	} + +	mTokenSizeStack.push_back(num_tokens_pushed); +	readAttributes(atts); +} + +bool LLSimpleXUIParser::readAttributes(const char **atts) +{ +	typedef boost::tokenizer<boost::char_separator<char> > tokenizer; +	boost::char_separator<char> sep("."); + +	bool any_parsed = false; +	for(S32 i = 0; atts[i] && atts[i+1]; i += 2 ) +	{ +		std::string attribute_name(atts[i]); +		mCurAttributeValueBegin = atts[i+1]; +		 +		S32 num_tokens_pushed = 0; +		tokenizer name_tokens(attribute_name, sep); +		// copy remaining tokens on to our running token list +		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push) +		{ +			mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration())); +			num_tokens_pushed++; +		} + +		// child nodes are not necessarily valid attributes, so don't complain once we've recursed +		bool silent = mCurReadDepth > 1; +		any_parsed |= mBlock->submitValue(mNameStack, *this, silent); +		 +		while(num_tokens_pushed-- > 0) +		{ +			mNameStack.pop_back(); +		} +	} +	return any_parsed; +} + + +void LLSimpleXUIParser::endElement(const char *name) +{ +	if (!mTextContents.empty()) +	{ +		LLStringUtil::trim(mTextContents); +		if (!mTextContents.empty()) +		{ +			mNameStack.push_back(std::make_pair(std::string("value"), newParseGeneration())); +			mCurAttributeValueBegin = mTextContents.c_str(); +			mBlock->submitValue(mNameStack, *this, false); +			mNameStack.pop_back(); +			mTextContents.clear(); +		} +	} +	mCurReadDepth--; +	S32 num_tokens_to_pop = mTokenSizeStack.back(); +	mTokenSizeStack.pop_back(); +	while(num_tokens_to_pop-- > 0) +	{ +		mNameStack.pop_back(); +	} +	mScope.pop_back(); +} + +void LLSimpleXUIParser::characterData(const char *s, int len) +{ +	mTextContents += std::string(s, len); +} + + +/*virtual*/ std::string LLSimpleXUIParser::getCurrentElementName() +{ +	std::string full_name; +	for (name_stack_t::iterator it = mNameStack.begin();	 +		it != mNameStack.end(); +		++it) +	{ +		full_name += it->first + "."; // build up dotted names: "button.param.nestedparam." +	} + +	return full_name; +} + +const S32 LINE_NUMBER_HERE = 0; + +void LLSimpleXUIParser::parserWarning(const std::string& message) +{ +#ifdef LL_WINDOWS +	// use Visual Studo friendly formatting of output message for easy access to originating xml +	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str()); +	utf16str += '\n'; +	OutputDebugString(utf16str.c_str()); +#else +	Parser::parserWarning(message); +#endif +} + +void LLSimpleXUIParser::parserError(const std::string& message) +{ +#ifdef LL_WINDOWS +	llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str()); +	utf16str += '\n'; +	OutputDebugString(utf16str.c_str()); +#else +	Parser::parserError(message); +#endif +} + +bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	if (!strcmp(self.mCurAttributeValueBegin, "true"))  +	{ +		*((bool*)val_ptr) = true; +		return true; +	} +	else if (!strcmp(self.mCurAttributeValueBegin, "false")) +	{ +		*((bool*)val_ptr) = false; +		return true; +	} + +	return false; +} + +bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	*((std::string*)val_ptr) = self.mCurAttributeValueBegin; +	return true; +} + +bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full; +} +	 +bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	LLColor4 value; + +	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) +	{ +		*(LLColor4*)(val_ptr) = value; +		return true; +	} +	return false; +} + +bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	LLColor4 value; +	LLUIColor* colorp = (LLUIColor*)val_ptr; + +	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) +	{ +		colorp->set(value); +		return true; +	} +	return false; +} + +bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	LLUUID temp_id; +	// LLUUID::set is destructive, so use temporary value +	if (temp_id.set(std::string(self.mCurAttributeValueBegin))) +	{ +		*(LLUUID*)(val_ptr) = temp_id; +		return true; +	} +	return false; +} + +bool LLSimpleXUIParser::readSDValue(Parser& parser, void* val_ptr) +{ +	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); +	*((LLSD*)val_ptr) = LLSD(self.mCurAttributeValueBegin); +	return true; +} diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h index 884f4f7578..eb7147f49e 100644 --- a/indra/llxuixml/llxuiparser.h +++ b/indra/llxuixml/llxuiparser.h @@ -120,26 +120,24 @@ public:  	void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL);  private: -	typedef std::list<std::pair<std::string, bool> >	token_list_t; -  	bool readXUIImpl(LLXMLNodePtr node, const std::string& scope, LLInitParam::BaseBlock& block);  	bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block);  	//reader helper functions -	bool readBoolValue(void* val_ptr); -	bool readStringValue(void* val_ptr); -	bool readU8Value(void* val_ptr); -	bool readS8Value(void* val_ptr); -	bool readU16Value(void* val_ptr); -	bool readS16Value(void* val_ptr); -	bool readU32Value(void* val_ptr); -	bool readS32Value(void* val_ptr); -	bool readF32Value(void* val_ptr); -	bool readF64Value(void* val_ptr); -	bool readColor4Value(void* val_ptr); -	bool readUIColorValue(void* val_ptr); -	bool readUUIDValue(void* val_ptr); -	bool readSDValue(void* val_ptr); +	static bool readBoolValue(Parser& parser, void* val_ptr); +	static bool readStringValue(Parser& parser, void* val_ptr); +	static bool readU8Value(Parser& parser, void* val_ptr); +	static bool readS8Value(Parser& parser, void* val_ptr); +	static bool readU16Value(Parser& parser, void* val_ptr); +	static bool readS16Value(Parser& parser, void* val_ptr); +	static bool readU32Value(Parser& parser, void* val_ptr); +	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 readColor4Value(Parser& parser, void* val_ptr); +	static bool readUIColorValue(Parser& parser, void* val_ptr); +	static bool readUUIDValue(Parser& parser, void* val_ptr); +	static bool readSDValue(Parser& parser, void* val_ptr);  	//writer helper functions  	bool writeBoolValue(const void* val_ptr, const name_stack_t&); @@ -173,5 +171,74 @@ private:  	std::string						mCurFileName;  }; +// LLSimpleXUIParser is a streamlined SAX-based XUI parser that does not support localization  +// or parsing of a tree of independent param blocks, such as child widgets. +// Use this for reading non-localized files that only need a single param block as a result. +// +// NOTE: In order to support nested block parsing, we need callbacks for start element that +// push new blocks contexts on the mScope stack. +// NOTE: To support localization without building a DOM, we need to enforce consistent  +// ordering of child elements from base file to localized diff file.  Then we can use a pair +// of coroutines to perform matching of xml nodes during parsing.  Not sure if the overhead +// of coroutines would offset the gain from SAX parsing + +class LLSimpleXUIParser : public LLInitParam::Parser, public LLSingleton<LLSimpleXUIParser> +{ +LOG_CLASS(LLSimpleXUIParser); + +protected: +	LLSimpleXUIParser(); +	virtual ~LLSimpleXUIParser(); +	friend class LLSingleton<LLSimpleXUIParser>; +public: +	typedef LLInitParam::Parser::name_stack_t name_stack_t; + +	/*virtual*/ std::string getCurrentElementName(); +	/*virtual*/ void parserWarning(const std::string& message); +	/*virtual*/ void parserError(const std::string& message); + +	bool readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent=false); +	void setBlock(LLInitParam::BaseBlock* block); + +private: +	//reader helper functions +	static bool readBoolValue(Parser&, void* val_ptr); +	static bool readStringValue(Parser&, void* val_ptr); +	static bool readU8Value(Parser&, void* val_ptr); +	static bool readS8Value(Parser&, void* val_ptr); +	static bool readU16Value(Parser&, void* val_ptr); +	static bool readS16Value(Parser&, void* val_ptr); +	static bool readU32Value(Parser&, void* val_ptr); +	static bool readS32Value(Parser&, void* val_ptr); +	static bool readF32Value(Parser&, void* val_ptr); +	static bool readF64Value(Parser&, void* val_ptr); +	static bool readColor4Value(Parser&, void* val_ptr); +	static bool readUIColorValue(Parser&, void* val_ptr); +	static bool readUUIDValue(Parser&, void* val_ptr); +	static bool readSDValue(Parser&, void* val_ptr); + +private: +	static void startElementHandler(void *userData, const char *name, const char **atts); +	static void endElementHandler(void *userData, const char *name); +	static void characterDataHandler(void *userData, const char *s, int len); + +	void startElement(const char *name, const char **atts); +	void endElement(const char *name); +	void characterData(const char *s, int len); +	bool readAttributes(const char **atts); + +	LLInitParam::BaseBlock*			mBlock; +	Parser::name_stack_t			mNameStack; +	struct XML_ParserStruct*		mParser; +	S32								mLastWriteGeneration; +	LLXMLNodePtr					mLastWrittenChild; +	S32								mCurReadDepth; +	std::string						mCurFileName; +	std::string						mTextContents; +	const char*						mCurAttributeValueBegin; +	std::vector<S32>				mTokenSizeStack; +	std::vector<std::string>		mScope; +}; +  #endif //LLXUIPARSER_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 64bcf12b06..7d70b2a49b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -230,6 +230,7 @@ set(viewer_SOURCE_FILES      llgroupiconctrl.cpp      llgrouplist.cpp      llgroupmgr.cpp +    llhints.cpp      llhomelocationresponder.cpp      llhudeffect.cpp      llhudeffectbeam.cpp @@ -300,6 +301,7 @@ set(viewer_SOURCE_FILES      llnotificationalerthandler.cpp      llnotificationgrouphandler.cpp      llnotificationhandlerutil.cpp +    llnotificationhinthandler.cpp      llnotificationmanager.cpp      llnotificationofferhandler.cpp      llnotificationscripthandler.cpp @@ -754,6 +756,7 @@ set(viewer_HEADER_FILES      llgroupiconctrl.h      llgrouplist.h      llgroupmgr.h +    llhints.h      llhomelocationresponder.h      llhudeffect.h      llhudeffectbeam.h @@ -1300,6 +1303,7 @@ set(viewer_APPSETTINGS_FILES      app_settings/cmd_line.xml      app_settings/grass.xml      app_settings/high_graphics.xml +    app_settings/ignorable_dialogs.xml      app_settings/keys.ini      app_settings/keywords.ini      app_settings/logcontrol.xml diff --git a/indra/newview/app_settings/ignorable_dialogs.xml b/indra/newview/app_settings/ignorable_dialogs.xml index d0e1f62a84..0720ccee49 100644 --- a/indra/newview/app_settings/ignorable_dialogs.xml +++ b/indra/newview/app_settings/ignorable_dialogs.xml @@ -1,10 +1,10 @@  <?xml version="1.0" ?>  <llsd>  <map> -    <key>FirstAppearance</key> +    <key>FirstInventoryOffer</key>      <map>        <key>Comment</key> -      <string>Enables FirstAppearance warning dialog</string> +      <string>Shows hint when a person or object offers resident an inventory item</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -12,120 +12,54 @@        <key>Value</key>        <integer>1</integer>      </map> -    <key>FirstAttach</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstAttach warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstBalanceDecrease</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstBalanceDecrease warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstBalanceIncrease</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstBalanceIncrease warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstBuild</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstBuild warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstDebugMenus</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstDebugMenus warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstFlexible</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstFlexible warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstGoTo</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstGoTo warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstInventory</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstInventory warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstLeftClickNoHit</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstLeftClickNoHit warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstMap</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstMap warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstMedia</key> +  <key>FirstNotUseDestinationGuide</key> +  <map> +    <key>Comment</key> +    <string>Shows hint when resident doesn't activate destination guide</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>1</integer> +  </map> +  <key>FirstNotUseSidePanel</key> +  <map> +    <key>Comment</key> +    <string>Shows hint when resident doesn't activate side panel</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>1</integer> +  </map> +  <key>FirstNotMoving</key> +  <map> +    <key>Comment</key> +    <string>Shows hint when resident doesn't move</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>1</integer> +  </map> +  <key>FirstReceiveLindens</key> +  <map> +    <key>Comment</key> +    <string>Shows hint when resident receives linden dollars</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>1</integer> +  </map> +  <key>FirstOtherChatBeforeUser</key>      <map>        <key>Comment</key> -      <string>Enables FirstMedia warning dialog</string> +      <string>Shows hint when someone else chats first</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -155,43 +89,11 @@        <key>Value</key>        <integer>1</integer>      </map> -    <key>FirstSculptedPrim</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstSculptedPrim warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> +      <key>FirstSit</key>      <map>        <key>Comment</key> -      <string>Enables FirstSit warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstTeleport</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstTeleport warning dialog</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map> -    <key>FirstVoice</key> -    <map> -      <key>Comment</key> -      <string>Enables FirstVoice warning dialog</string> +      <string>Shows hint when someone sits for the first time</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4c52fb015f..12fb8741ca 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6425,6 +6425,17 @@          <key>Value</key>              <real>1.0</real>          </map> +    <key>MediaBrowserWindowLimit</key> +    <map> +      <key>Comment</key> +      <string>Maximum number of media brower windows that can be open at once (0 for no limit)</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>5</integer> +    </map>    <key>MediaRollOffRate</key>    <map>      <key>Comment</key> @@ -11936,5 +11947,38 @@        <key>Value</key>        <integer>10</integer>      </map> +    <key>NotMovingHintTimeout</key> +    <map> +      <key>Comment</key> +      <string>Number of seconds to wait for resident to move before displaying move hint.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>F32</string> +      <key>Value</key> +      <real>120.0</real> +    </map> +    <key>DestinationGuideHintTimeout</key> +    <map> +      <key>Comment</key> +      <string>Number of seconds to wait before telling resident about destination guide.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>F32</string> +      <key>Value</key> +      <real>600.0</real> +    </map> +    <key>SidePanelHintTimeout</key> +    <map> +      <key>Comment</key> +      <string>Number of seconds to wait before telling resident about side panel.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>F32</string> +      <key>Value</key> +      <real>300.0</real> +    </map>  </map>  </llsd> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index e85d108bb2..70bda3893e 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -44,6 +44,7 @@  #include "llcallingcard.h"  #include "llchannelmanager.h"  #include "llconsole.h" +#include "llfirstuse.h"  #include "llfloatercamera.h"  #include "llfloaterreg.h"  #include "llfloatertools.h" @@ -232,8 +233,9 @@ LLAgent::LLAgent() :  		mControlsTakenPassedOnCount[i] = 0;  	} -  	mListener.reset(new LLAgentListener(*this)); + +	mMoveTimer.stop();  }  // Requires gSavedSettings to be initialized. @@ -242,6 +244,8 @@ LLAgent::LLAgent() :  //-----------------------------------------------------------------------------  void LLAgent::init()  { +	mMoveTimer.start(); +  	gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", FALSE);  	gSavedSettings.getControl("SlowMotionAnimation")->getSignal()->connect(boost::bind(&handleSlowMotionAnimation, _2)); @@ -306,6 +310,9 @@ void LLAgent::ageChat()  //-----------------------------------------------------------------------------  void LLAgent::moveAt(S32 direction, bool reset)  { +	mMoveTimer.reset(); +	LLFirstUse::notMoving(false); +  	// age chat timer so it fades more quickly when you are intentionally moving  	ageChat(); @@ -331,6 +338,9 @@ void LLAgent::moveAt(S32 direction, bool reset)  //-----------------------------------------------------------------------------  void LLAgent::moveAtNudge(S32 direction)  { +	mMoveTimer.reset(); +	LLFirstUse::notMoving(false); +  	// age chat timer so it fades more quickly when you are intentionally moving  	ageChat(); @@ -353,6 +363,9 @@ void LLAgent::moveAtNudge(S32 direction)  //-----------------------------------------------------------------------------  void LLAgent::moveLeft(S32 direction)  { +	mMoveTimer.reset(); +	LLFirstUse::notMoving(false); +  	// age chat timer so it fades more quickly when you are intentionally moving  	ageChat(); @@ -375,6 +388,9 @@ void LLAgent::moveLeft(S32 direction)  //-----------------------------------------------------------------------------  void LLAgent::moveLeftNudge(S32 direction)  { +	mMoveTimer.reset(); +	LLFirstUse::notMoving(false); +  	// age chat timer so it fades more quickly when you are intentionally moving  	ageChat(); @@ -397,6 +413,9 @@ void LLAgent::moveLeftNudge(S32 direction)  //-----------------------------------------------------------------------------  void LLAgent::moveUp(S32 direction)  { +	mMoveTimer.reset(); +	LLFirstUse::notMoving(false); +  	// age chat timer so it fades more quickly when you are intentionally moving  	ageChat(); @@ -1534,6 +1553,12 @@ void LLAgent::propagate(const F32 dt)  //-----------------------------------------------------------------------------  void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y)  { +	if (mMoveTimer.getStarted() && mMoveTimer.getElapsedTimeF32() > gSavedSettings.getF32("NotMovingHintTimeout")) +	{ +		LLFirstUse::notMoving(); +		mMoveTimer.stop(); +	} +  	propagate(dt);  	// static S32 cameraUpdateCount = 0; diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 32f9b00135..0185f874f9 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -270,6 +270,7 @@ public:  private:  	LLFrameTimer	mFidgetTimer;  	LLFrameTimer	mFocusObjectFadeTimer; +	LLFrameTimer	mMoveTimer;  	F32				mNextFidgetTime;  	S32				mCurrentFidget; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d222d94ec6..768be116f6 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -268,6 +268,7 @@ const F64 FRAME_STALL_THRESHOLD = 1.0;  LLTimer gRenderStartTime;  LLFrameTimer gForegroundTime; +LLFrameTimer gLoggedInTime;  LLTimer gLogoutTimer;  static const F32 LOGOUT_REQUEST_TIME = 6.f;  // this will be cut short by the LogoutReply msg.  F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME; @@ -597,6 +598,7 @@ LLAppViewer::LLAppViewer() :  	setupErrorHandling();  	sInstance = this; +	gLoggedInTime.stop();  }  LLAppViewer::~LLAppViewer() @@ -4281,6 +4283,7 @@ void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)  void LLAppViewer::handleLoginComplete()  { +	gLoggedInTime.start();  	initMainloopTimeout("Mainloop Init");  	// Store some data to DebugInfo in case of a freeze. diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 0b862a92a1..e5e27dc908 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -313,6 +313,7 @@ extern U32 		gFrameStalls;  extern LLTimer gRenderStartTime;  extern LLFrameTimer gForegroundTime; +extern LLFrameTimer gLoggedInTime;  extern F32 gLogoutMaxTime;  extern LLTimer gLogoutTimer; diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 0e5e8d0fe7..e0b605a724 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -47,6 +47,7 @@  #include "llagentcamera.h"  #include "llchiclet.h"  #include "llfloatercamera.h" +#include "llhints.h"  #include "llimfloater.h" // for LLIMFloater  #include "llnearbychatbar.h"  #include "llspeakbutton.h" @@ -68,10 +69,6 @@ template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();  namespace  {  	const std::string& PANEL_CHICLET_NAME	= "chiclet_list_panel"; -	const std::string& PANEL_CHATBAR_NAME	= "chat_bar"; -	const std::string& PANEL_MOVEMENT_NAME	= "movement_panel"; -	const std::string& PANEL_CAMERA_NAME	= "cam_panel"; -	const std::string& PANEL_GESTURE_NAME	= "gesture_panel";  	S32 get_panel_min_width(LLLayoutStack* stack, LLView* panel)  	{ @@ -474,10 +471,12 @@ BOOL LLBottomTray::postBuild()  	mBottomTrayContextMenu =  LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_bottomtray.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());  	gMenuHolder->addChild(mBottomTrayContextMenu); -  	mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar"); +	LLHints::registerHintTarget("nearby_chat_bar", mNearbyChatBar->LLView::getHandle()); +  	mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");  	mMovementButton = getChild<LLButton>("movement_btn"); +	LLHints::registerHintTarget("move_btn", mMovementButton->getHandle());  	mCamButton = getChild<LLButton>("camera_btn");  	setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4)); diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 73fbe78298..96001a07a0 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -571,6 +571,10 @@ void LLChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type,  void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate)  { +	// as soon as we say something, we no longer care about teaching the user +	// how to chat +	gWarningSettings.setBOOL("FirstOtherChatBeforeUser", FALSE); +	  	// Look for "/20 foo" channel chats.  	S32 channel = 0;  	LLWString out_text = stripChannelNumber(wtext, &channel); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 8bc3b5a75f..696ac4e6fa 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -123,7 +123,7 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)  	{  		S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());  		bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY); -		mPrintStats = bar_idx; +		mPrintStats = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - bar_idx;  	}  	return FALSE;  } @@ -140,6 +140,17 @@ LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y)  	return NULL;  } +BOOL LLFastTimerView::handleDoubleClick(S32 x, S32 y, MASK mask) +{ +	for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer()); +		it != end_timer_tree(); +		++it) +	{ +		(*it)->setCollapsed(false); +	} +	return TRUE; +} +  BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)  { @@ -953,7 +964,7 @@ void LLFastTimerView::draw()  			{  				legend_stat += ", ";  			} -			first = true; +			first = false;  			legend_stat += idp->getName();  			if (idp->getCollapsed()) @@ -980,8 +991,7 @@ void LLFastTimerView::draw()  			U64 ticks;  			if (mPrintStats > 0)  			{ -				S32 hidx = (mPrintStats - 1) - mScrollIndex; -				ticks = idp->getHistoricalCount(hidx); +				ticks = idp->getHistoricalCount(mPrintStats);  			}  			else  			{ diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index ac06990913..6f64248f78 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -54,6 +54,7 @@ private:  public:  	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); +	virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);  	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);  	virtual BOOL handleHover(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp index b3fdf60b11..15de138c95 100644 --- a/indra/newview/llfirstuse.cpp +++ b/indra/newview/llfirstuse.cpp @@ -36,7 +36,7 @@  // library includes  #include "indra_constants.h" -#include "llnotificationsutil.h" +#include "llnotifications.h"  // viewer includes  #include "llagent.h"	// for gAgent.inPrelude() @@ -45,9 +45,10 @@  #include "llappviewer.h"  #include "lltracker.h" -/* +  // static  std::set<std::string> LLFirstUse::sConfigVariables; +std::map<std::string, LLNotificationPtr> LLFirstUse::sNotifications;  // static  void LLFirstUse::addConfigVariable(const std::string& var) @@ -76,211 +77,90 @@ void LLFirstUse::resetFirstUse()  		gWarningSettings.setBOOL(*iter, TRUE);  	}  } -*/ -/* - -// Called whenever the viewer detects that your balance went up -void LLFirstUse::useBalanceIncrease(S32 delta) -{ -	if (gWarningSettings.getBOOL("FirstBalanceIncrease")) -	{ -		gWarningSettings.setBOOL("FirstBalanceIncrease", FALSE); - -		LLSD args; -		args["AMOUNT"] = llformat("%d",delta); -		LLNotificationsUtil::add("FirstBalanceIncrease", args); -	} -} - -// Called whenever the viewer detects your balance went down -void LLFirstUse::useBalanceDecrease(S32 delta) +// static +void LLFirstUse::useOverrideKeys()  { -	if (gWarningSettings.getBOOL("FirstBalanceDecrease")) +	// Our orientation island uses key overrides to teach vehicle driving +	// so don't show this message until you get off OI. JC +	if (!gAgent.inPrelude())  	{ -		gWarningSettings.setBOOL("FirstBalanceDecrease", FALSE); - -		LLSD args; -		args["AMOUNT"] = llformat("%d",-delta); -		LLNotificationsUtil::add("FirstBalanceDecrease", args); +		firstUseNotification("FirstOverrideKeys", true, "FirstOverrideKeys");  	}  } - -// static -void LLFirstUse::useSit() -{ -	// Our orientation island uses sitting to teach vehicle driving -	// so just never show this message. JC -	//if (gWarningSettings.getBOOL("FirstSit")) -	//{ -	//	gWarningSettings.setBOOL("FirstSit", FALSE); -        // -	//	LLNotificationsUtil::add("FirstSit"); -	//} -} -  // static -void LLFirstUse::useMap() +void LLFirstUse::otherAvatarChatFirst(bool enable)  { -	if (gWarningSettings.getBOOL("FirstMap")) -	{ -		gWarningSettings.setBOOL("FirstMap", FALSE); - -		LLNotificationsUtil::add("FirstMap"); -	} +	firstUseNotification("FirstOtherChatBeforeUser", enable, "HintChat", LLSD(), LLSD().with("target", "nearby_chat_bar").with("direction", "top"));  }  // static -void LLFirstUse::useGoTo() +void LLFirstUse::sit(bool enable)  { -	// nothing for now JC +	firstUseNotification("FirstSit", enable, "HintSit", LLSD(), LLSD().with("target", "stand_btn").with("direction", "top"));  }  // static -void LLFirstUse::useBuild() +void LLFirstUse::inventoryOffer(bool enable)  { -	if (gWarningSettings.getBOOL("FirstBuild")) -	{ -		gWarningSettings.setBOOL("FirstBuild", FALSE); - -		LLNotificationsUtil::add("FirstBuild"); -	} +	firstUseNotification("FirstInventoryOffer", enable, "HintInventory", LLSD(), LLSD().with("target", "inventory_btn").with("direction", "left"));  } -  - */ -/* -// static -void LLFirstUse::useLeftClickNoHit() -{  -	if (gWarningSettings.getBOOL("FirstLeftClickNoHit")) -	{ -		gWarningSettings.setBOOL("FirstLeftClickNoHit", FALSE); -		LLNotificationsUtil::add("FirstLeftClickNoHit"); -	} -} -*/ -/*  // static -void LLFirstUse::useTeleport() +void LLFirstUse::useSandbox()  { -	if (gWarningSettings.getBOOL("FirstTeleport")) -	{ -		LLVector3d teleportDestination = LLTracker::getTrackedPositionGlobal(); -		if(teleportDestination != LLVector3d::zero) -		{ -			gWarningSettings.setBOOL("FirstTeleport", FALSE); - -		        LLNotificationsUtil::add("FirstTeleport"); -		} -	} +	firstUseNotification("FirstSandbox", true, "FirstSandbox", LLSD().with("HOURS", SANDBOX_CLEAN_FREQ).with("TIME", SANDBOX_FIRST_CLEAN_HOUR));  } -*/ -// static -void LLFirstUse::useOverrideKeys() -{ -	// Our orientation island uses key overrides to teach vehicle driving -	// so don't show this message until you get off OI. JC -	if (!gAgent.inPrelude()) -	{ -		if (gWarningSettings.getBOOL("FirstOverrideKeys")) -		{ -			gWarningSettings.setBOOL("FirstOverrideKeys", FALSE); -			LLNotificationsUtil::add("FirstOverrideKeys"); -		} -	} -} -/*  // static -void LLFirstUse::useAttach() +void LLFirstUse::notUsingDestinationGuide(bool enable)  { -	// nothing for now +	// not doing this yet +	//firstUseNotification("FirstNotUseDestinationGuide", enable, "HintDestinationGuide", LLSD(), LLSD().with("target", "dest_guide_btn").with("direction", "left"));  }  // static -void LLFirstUse::useAppearance() +void LLFirstUse::notUsingSidePanel(bool enable)  { -	if (gWarningSettings.getBOOL("FirstAppearance")) -	{ -		gWarningSettings.setBOOL("FirstAppearance", FALSE); - -		LLNotificationsUtil::add("FirstAppearance"); -	} +	// not doing this yet +	//firstUseNotification("FirstNotUseSidePanel", enable, "HintSidePanel", LLSD(), LLSD().with("target", "side_panel_btn").with("direction", "left"));  }  // static -void LLFirstUse::useInventory() +void LLFirstUse::notMoving(bool enable)  { -	if (gWarningSettings.getBOOL("FirstInventory")) -	{ -		gWarningSettings.setBOOL("FirstInventory", FALSE); - -		LLNotificationsUtil::add("FirstInventory"); -	} +	firstUseNotification("FirstNotMoving", enable, "HintMove", LLSD(), LLSD().with("target", "move_btn").with("direction", "top"));  } -*/ -  // static -void LLFirstUse::useSandbox() +void LLFirstUse::receiveLindens(bool enable)  { -	if (gWarningSettings.getBOOL("FirstSandbox")) -	{ -		gWarningSettings.setBOOL("FirstSandbox", FALSE); - -		LLSD args; -		args["HOURS"] = llformat("%d",SANDBOX_CLEAN_FREQ); -		args["TIME"] = llformat("%d",SANDBOX_FIRST_CLEAN_HOUR); -		LLNotificationsUtil::add("FirstSandbox", args); -	} +	firstUseNotification("FirstReceiveLindens", enable, "HintLindenDollar", LLSD(), LLSD().with("target", "linden_balance").with("direction", "bottom"));  } -/* -// static -void LLFirstUse::useFlexible() -{ -	if (gWarningSettings.getBOOL("FirstFlexible")) -	{ -		gWarningSettings.setBOOL("FirstFlexible", FALSE); -		LLNotificationsUtil::add("FirstFlexible"); -	} -} -// static -void LLFirstUse::useDebugMenus() +//static  +void LLFirstUse::firstUseNotification(const std::string& control_var, bool enable, const std::string& notification_name, LLSD args, LLSD payload)  { -	if (gWarningSettings.getBOOL("FirstDebugMenus")) -	{ -		gWarningSettings.setBOOL("FirstDebugMenus", FALSE); +	LLNotificationPtr notif = sNotifications[notification_name]; -		LLNotificationsUtil::add("FirstDebugMenus"); -	} -} - -// static -void LLFirstUse::useSculptedPrim() -{ -	if (gWarningSettings.getBOOL("FirstSculptedPrim")) +	if (enable)  	{ -		gWarningSettings.setBOOL("FirstSculptedPrim", FALSE); - -		LLNotificationsUtil::add("FirstSculptedPrim"); -		 +		if (!notif && gWarningSettings.getBOOL(control_var)) +		{ // create new notification +			sNotifications[notification_name] = LLNotifications::instance().add(LLNotification::Params().name(notification_name).substitutions(args).payload(payload)); +			gWarningSettings.setBOOL(control_var, FALSE); +		} +	}	 +	else +	{ // want to hide notification +		if (notif) +		{ // cancel existing notification +			LLNotifications::instance().cancel(notif); +			sNotifications.erase(notification_name); +		} +		gWarningSettings.setBOOL(control_var, FALSE);  	} -} -// static  -void LLFirstUse::useMedia() -{ -	if (gWarningSettings.getBOOL("FirstMedia")) -	{ -		gWarningSettings.setBOOL("FirstMedia", FALSE); - -		// Popup removed as a short-term fix for EXT-1643. -		// Ultimately, the plan is to kill all First Use dialogs -		//LLNotificationsUtil::add("FirstMedia"); -	}  } -*/ diff --git a/indra/newview/llfirstuse.h b/indra/newview/llfirstuse.h index 3c7551f6cb..48943cd9ab 100644 --- a/indra/newview/llfirstuse.h +++ b/indra/newview/llfirstuse.h @@ -76,10 +76,13 @@ object or from inventory.  14. First time you create/edit a sculpted prim.  */ +class LLNotification; + +  class LLFirstUse  {  public: -/*	 +  	// Add a config variable to be reset on resetFirstUse()  	static void addConfigVariable(const std::string& var); @@ -87,35 +90,20 @@ public:  	static void disableFirstUse();  	static void resetFirstUse(); -	// These methods are called each time the appropriate action is -	// taken.  The functions themselves handle only showing the dialog -	// the first time, or subsequent times if the user wishes. -	static void useBalanceIncrease(S32 delta); -	static void useBalanceDecrease(S32 delta); -	static void useSit(); -	static void useMap(); -	static void useGoTo(); -	static void useBuild(); -//	static void useLeftClickNoHit(); -	static void useTeleport(); -*/   	static void useOverrideKeys(); -/*	 -	static void useAttach(); -	static void useAppearance(); -	static void useInventory(); - */ +	static void otherAvatarChatFirst(bool enable = true); +	static void sit(bool enable = true); +	static void notUsingDestinationGuide(bool enable = true); +	static void notUsingSidePanel(bool enable = true); +	static void notMoving(bool enable = true); +	static void inventoryOffer(bool enable = true); +	static void receiveLindens(bool enable = true);  	static void useSandbox(); -/* -	static void useFlexible(); -	static void useDebugMenus(); -	static void useSculptedPrim(); -	static void useMedia(); -	  protected: +	static void firstUseNotification(const std::string& control_var, bool enable, const std::string& notification_name, LLSD args = LLSD(), LLSD payload = LLSD());  	static std::set<std::string> sConfigVariables; -*/ +	static std::map<std::string, boost::shared_ptr<LLNotification> > sNotifications;  };  #endif diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp index 43f158658a..834f517734 100644 --- a/indra/newview/llfloatergroups.cpp +++ b/indra/newview/llfloatergroups.cpp @@ -344,11 +344,10 @@ void LLPanelGroups::onGroupList(LLUICtrl* ctrl, void* userdata)  	if(self) self->enableButtons();  } -void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 powers_mask) +void init_group_list(LLScrollListCtrl* group_list, const LLUUID& highlight_id, U64 powers_mask)  {  	S32 count = gAgent.mGroups.count();  	LLUUID id; -	LLCtrlListInterface *group_list = ctrl->getListInterface();  	if (!group_list) return;  	group_list->operateOnAll(LLCtrlListInterface::OP_DELETE); @@ -372,10 +371,12 @@ void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 pow  			element["columns"][0]["font"]["name"] = "SANSSERIF";  			element["columns"][0]["font"]["style"] = style; -			group_list->addElement(element, ADD_SORTED); +			group_list->addElement(element);  		}  	} +	group_list->sortOnce(0, TRUE); +  	// add "none" to list at top  	{  		std::string style = "NORMAL"; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 625b443abc..19e28720ae 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2440,7 +2440,7 @@ void LLPanelLandAccess::refresh()  					suffix.append(" " + parent_floater->getString("Remaining") + ")");  				}  				if (mListAccess) -					mListAccess->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix); +					mListAccess->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix);  			}  		} @@ -2481,7 +2481,7 @@ void LLPanelLandAccess::refresh()  					}  					suffix.append(" " + parent_floater->getString("Remaining") + ")");  				} -				mListBanned->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix); +				mListBanned->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix);  			}  		} diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp index 3c8ee6eb9e..12d27b8790 100644 --- a/indra/newview/llfloaterlandholdings.cpp +++ b/indra/newview/llfloaterlandholdings.cpp @@ -75,10 +75,9 @@ BOOL LLFloaterLandHoldings::postBuild()  	childSetAction("Show on Map", onClickMap, this);  	// Grant list -	getChild<LLScrollListCtrl>("grant list")->setDoubleClickCallback(onGrantList, this); - -	LLCtrlListInterface *list = childGetListInterface("grant list"); -	if (!list) return TRUE; +	LLScrollListCtrl* grant_list = getChild<LLScrollListCtrl>("grant list"); +	grant_list->sortByColumnIndex(0, TRUE); +	grant_list->setDoubleClickCallback(onGrantList, this);  	S32 count = gAgent.mGroups.count();  	for(S32 i = 0; i < count; ++i) @@ -97,7 +96,7 @@ BOOL LLFloaterLandHoldings::postBuild()  		element["columns"][1]["value"] = areastr;  		element["columns"][1]["font"] = "SANSSERIF"; -		list->addElement(element, ADD_SORTED); +		grant_list->addElement(element);  	}  	center(); diff --git a/indra/newview/llfloatermediabrowser.cpp b/indra/newview/llfloatermediabrowser.cpp index 5405de2f9a..90147ff650 100644 --- a/indra/newview/llfloatermediabrowser.cpp +++ b/indra/newview/llfloatermediabrowser.cpp @@ -63,6 +63,54 @@ LLFloaterMediaBrowser::LLFloaterMediaBrowser(const LLSD& key)  } +//static  +void LLFloaterMediaBrowser::create(const std::string &url, const std::string& target) +{ +	std::string tag = target; +	 +	if(target.empty() || target == "_blank") +	{ +		// create a unique tag for this instance +		LLUUID id; +		id.generate(); +		tag = id.asString(); +	} +	 +	S32 browser_window_limit = gSavedSettings.getS32("MediaBrowserWindowLimit"); +	 +	if(LLFloaterReg::findInstance("media_browser", tag) != NULL) +	{ +		// There's already a media browser for this tag, so we won't be opening a new window. +	} +	else if(browser_window_limit != 0) +	{ +		// showInstance will open a new window.  Figure out how many media browsers are already open,  +		// and close the least recently opened one if this will put us over the limit. +		 +		LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("media_browser"); +		lldebugs << "total instance count is " << instances.size() << llendl; +		 +		for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) +		{ +			lldebugs << "    " << (*iter)->getKey() << llendl; +		} +		 +		if(instances.size() >= (size_t)browser_window_limit) +		{ +			// Destroy the least recently opened instance +			(*instances.begin())->closeFloater(); +		} +	} + +	LLFloaterMediaBrowser *browser = dynamic_cast<LLFloaterMediaBrowser*> (LLFloaterReg::showInstance("media_browser", tag)); +	llassert(browser); +	if(browser) +	{ +		// tell the browser instance to load the specified URL +		browser->openMedia(url); +	} +} +  void LLFloaterMediaBrowser::draw()  {  	getChildView("go")->setEnabled(!mAddressCombo->getValue().asString().empty()); @@ -105,6 +153,7 @@ BOOL LLFloaterMediaBrowser::postBuild()  	mAddressCombo = getChild<LLComboBox>("address");  	mAddressCombo->setCommitCallback(onEnterAddress, this); +	mAddressCombo->sortByName();  	childSetAction("back", onClickBack, this);  	childSetAction("forward", onClickForward, this); @@ -185,7 +234,7 @@ void LLFloaterMediaBrowser::setCurrentURL(const std::string& url)  	if (mCurrentURL != "about:blank")  	{  		mAddressCombo->remove(mCurrentURL); -		mAddressCombo->add(mCurrentURL, ADD_SORTED); +		mAddressCombo->add(mCurrentURL);  		mAddressCombo->selectByValue(mCurrentURL);  		// Serialize url history @@ -197,12 +246,6 @@ void LLFloaterMediaBrowser::setCurrentURL(const std::string& url)  	getChildView("reload")->setEnabled(TRUE);  } -void LLFloaterMediaBrowser::onOpen(const LLSD& media_url) -{ -	LLFloater::onOpen(media_url); -	openMedia(media_url.asString()); -} -  //static   void LLFloaterMediaBrowser::onEnterAddress(LLUICtrl* ctrl, void* user_data)  { diff --git a/indra/newview/llfloatermediabrowser.h b/indra/newview/llfloatermediabrowser.h index c315f9e797..4255d814c0 100644 --- a/indra/newview/llfloatermediabrowser.h +++ b/indra/newview/llfloatermediabrowser.h @@ -45,12 +45,14 @@ class LLFloaterMediaBrowser :  	public LLViewerMediaObserver  {  public: +    LOG_CLASS(LLFloaterMediaBrowser);  	LLFloaterMediaBrowser(const LLSD& key); +	static void create(const std::string &url, const std::string& target); +	  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void onClose(bool app_quitting);  	/*virtual*/ void draw(); -	/*virtual*/ void onOpen(const LLSD& key);  	// inherited from LLViewerMediaObserver  	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 7791c037d3..a4b45e04f2 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -826,13 +826,11 @@ void LLFloaterPreference::buildPopupLists()  				row["columns"][1]["font"] = "SANSSERIF_SMALL";  				row["columns"][1]["width"] = 360;  			} -			item = disabled_popups.addElement(row, -											  ADD_SORTED); +			item = disabled_popups.addElement(row);  		}  		else  		{ -			item = enabled_popups.addElement(row, -											 ADD_SORTED); +			item = enabled_popups.addElement(row);  		}  		if (item) diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index e0f646349e..a77fc4710a 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -712,38 +712,44 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)  				}  			} -			LLSD element; +			LLScrollListItem::Params item_params; +			item_params.value = task_id; -			element["id"] = task_id; -			element["columns"][0]["column"] = "size"; -			element["columns"][0]["value"] = llformat("%d", size); -			element["columns"][0]["font"] = "SANSSERIF"; -			element["columns"][1]["column"] = "urls"; -			element["columns"][1]["value"] = llformat("%d", urls); -			element["columns"][1]["font"] = "SANSSERIF"; -			element["columns"][2]["column"] = "name"; -			element["columns"][2]["value"] = name_buf; -			element["columns"][2]["font"] = "SANSSERIF"; -			element["columns"][3]["column"] = "owner"; -			element["columns"][3]["value"] = owner_buf; -			element["columns"][3]["font"] = "SANSSERIF"; -			element["columns"][4]["column"] = "parcel"; -			element["columns"][4]["value"] = parcel_name; -			element["columns"][4]["font"] = "SANSSERIF"; -			element["columns"][5]["column"] = "location"; -			if(has_locations) -			{ -				element["columns"][5]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z); -			} -			else -			{ -				element["columns"][5]["value"] = ""; -			} -			element["columns"][5]["font"] = "SANSSERIF"; +			LLScrollListCell::Params cell_params; +			cell_params.font = LLFontGL::getFontSansSerif(); + +			cell_params.column = "size"; +			cell_params.value = size; +			item_params.columns.add(cell_params); + +			cell_params.column = "urls"; +			cell_params.value = urls; +			item_params.columns.add(cell_params); + +			cell_params.column = "name"; +			cell_params.value = name_buf; +			item_params.columns.add(cell_params); -			list->addElement(element, ADD_SORTED); +			cell_params.column = "owner"; +			cell_params.value = owner_buf; +			item_params.columns.add(cell_params); + +			cell_params.column = "parcel"; +			cell_params.value = parcel_name; +			item_params.columns.add(cell_params); + +			cell_params.column = "location"; +			cell_params.value = has_locations +				? llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z) +				: ""; +			item_params.columns.add(cell_params); + +			list->addRow(item_params); +			LLSD element;  			element["owner_id"] = owner_id; + +			element["id"] = task_id;  			element["local_id"] = local_id;  			mObjectListItems.push_back(element);  		} diff --git a/indra/newview/llhints.cpp b/indra/newview/llhints.cpp new file mode 100644 index 0000000000..14a9871a7d --- /dev/null +++ b/indra/newview/llhints.cpp @@ -0,0 +1,304 @@ +/** + * @file llhints.cpp + * @brief Hint popups for displaying context sensitive help in a UI overlay + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" // must be first include + +#include "llhints.h" + +#include "llbutton.h" +#include "lltextbox.h" +#include "llviewerwindow.h" +#include "llsdparam.h" + +class LLHintPopup : public LLPanel +{ +public: + +	typedef enum e_popup_direction +	{ +		LEFT, +		TOP, +		RIGHT, +		BOTTOM +	} EPopupDirection; + +	struct PopupDirections : public LLInitParam::TypeValuesHelper<LLHintPopup::EPopupDirection, PopupDirections> +	{ +		static void declareValues() +		{ +			declare("left", LLHintPopup::LEFT); +			declare("right", LLHintPopup::RIGHT); +			declare("top", LLHintPopup::TOP); +			declare("bottom", LLHintPopup::BOTTOM); +		} +	}; + +	struct Params : public LLInitParam::Block<Params, LLPanel::Params> +	{ +		Mandatory<LLNotificationPtr>	notification; +		Optional<std::string>			target; +		Optional<EPopupDirection, PopupDirections>	direction; +		Optional<S32>					distance; +		Optional<LLUIImage*>			left_arrow, +										up_arrow, +										right_arrow, +										down_arrow;	 +		Optional<S32>					left_arrow_offset, +										up_arrow_offset, +										right_arrow_offset, +										down_arrow_offset; +		Optional<F32>					fade_in_time, +										fade_out_time; + +		Params() +		:	direction("direction", TOP), +			distance("distance", 24), +			target("target"), +			left_arrow("left_arrow", LLUI::getUIImage("hint_arrow_left")), +			up_arrow("up_arrow", LLUI::getUIImage("hint_arrow_up")), +			right_arrow("right_arrow", LLUI::getUIImage("hint_arrow_right")), +			down_arrow("down_arrow", LLUI::getUIImage("hint_arrow_down")), +			left_arrow_offset("left_arrow_offset", 3), +			up_arrow_offset("up_arrow_offset", -2), +			right_arrow_offset("right_arrow_offset", -3), +			down_arrow_offset("down_arrow_offset", 5), +			fade_in_time("fade_in_time", 0.2f), +			fade_out_time("fade_out_time", 0.5f) +		{} +	}; + +	LLHintPopup(const Params&); + +	void setHintTarget(LLHandle<LLView> target) { mTarget = target; } +	/*virtual*/ BOOL postBuild(); + +	void onClickClose() { hide(); } +	void draw(); +	void hide() { if(!mHidden) {mHidden = true; mFadeTimer.reset();} } + +private: +	LLNotificationPtr	mNotification; +	LLHandle<LLView>	mTarget; +	EPopupDirection		mDirection; +	S32					mDistance; +	LLUIImagePtr		mArrowLeft, +						mArrowUp, +						mArrowRight, +						mArrowDown; +	S32					mArrowLeftOffset, +						mArrowUpOffset, +						mArrowRightOffset, +						mArrowDownOffset; +	LLFrameTimer		mFadeTimer; +	F32					mFadeInTime, +						mFadeOutTime; +	bool				mHidden; +}; + + + + +LLHintPopup::LLHintPopup(const LLHintPopup::Params& p) +:	mNotification(p.notification), +	mDirection(p.direction), +	mDistance(p.distance), +	mTarget(LLHints::getHintTarget(p.target)), +	mArrowLeft(p.left_arrow), +	mArrowUp(p.up_arrow), +	mArrowRight(p.right_arrow), +	mArrowDown(p.down_arrow), +	mArrowLeftOffset(p.left_arrow_offset), +	mArrowUpOffset(p.up_arrow_offset), +	mArrowRightOffset(p.right_arrow_offset), +	mArrowDownOffset(p.down_arrow_offset), +	mHidden(false), +	mFadeInTime(p.fade_in_time), +	mFadeOutTime(p.fade_out_time), +	LLPanel(p) +{ +	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_hint.xml"); +} + +BOOL LLHintPopup::postBuild() +{ +	LLTextBox& hint_text = getChildRef<LLTextBox>("hint_text"); +	hint_text.setText(mNotification->getMessage()); +	 +	getChild<LLButton>("close")->setClickedCallback(boost::bind(&LLHintPopup::onClickClose, this)); +	getChild<LLTextBox>("hint_title")->setText(mNotification->getLabel()); + +	LLRect text_bounds = hint_text.getTextBoundingRect(); +	S32 delta_height = text_bounds.getHeight() - hint_text.getRect().getHeight(); +	reshape(getRect().getWidth(), getRect().getHeight() + delta_height); +	return TRUE; +} + +void LLHintPopup::draw() +{ +	F32 alpha = 1.f; +	if (mHidden) +	{ +		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, mFadeOutTime, 1.f, 0.f); +		if (alpha == 0.f) +		{ +			die(); +		} +	} +	else +	{ +		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, mFadeInTime, 0.f, 1.f); +	} +	LLViewDrawContext context(alpha); + +	LLView* targetp = mTarget.get(); +	if (!targetp || !targetp->isInVisibleChain())  +	{ +		hide(); +	} +	else +	{ +		LLRect target_rect; +		targetp->localRectToOtherView(targetp->getLocalRect(), &target_rect, getParent()); + +		LLRect my_local_rect = getLocalRect(); +		LLRect my_rect; +		LLRect arrow_rect; +		LLUIImagePtr arrow_imagep; + +		switch(mDirection) +		{ +		case LEFT: +			my_rect.setCenterAndSize(	target_rect.mLeft - (my_local_rect.getWidth() / 2 + mDistance),  +										target_rect.getCenterY(),  +										my_local_rect.getWidth(),  +										my_local_rect.getHeight()); +			arrow_rect.setCenterAndSize(my_local_rect.mRight + mArrowRight->getWidth() / 2 + mArrowRightOffset, +										my_local_rect.getCenterY(), +										mArrowRight->getWidth(),  +										mArrowRight->getHeight()); +			arrow_imagep = mArrowRight; +			break; +		case TOP: +			my_rect.setCenterAndSize(	target_rect.getCenterX(),  +										target_rect.mTop + (my_local_rect.getHeight() / 2 + mDistance),  +										my_local_rect.getWidth(),  +										my_local_rect.getHeight()); +			arrow_rect.setCenterAndSize(my_local_rect.getCenterX(), +										my_local_rect.mBottom - mArrowDown->getHeight() / 2 + mArrowDownOffset, +										mArrowDown->getWidth(),  +										mArrowDown->getHeight()); +			arrow_imagep = mArrowDown; +			break; +		case RIGHT: +			my_rect.setCenterAndSize(	target_rect.getCenterX(),  +										target_rect.mTop - (my_local_rect.getHeight() / 2 + mDistance),  +										my_local_rect.getWidth(),  +										my_local_rect.getHeight()); +			arrow_rect.setCenterAndSize(my_local_rect.mLeft - mArrowLeft->getWidth() / 2 + mArrowLeftOffset, +										my_local_rect.getCenterY(), +										mArrowLeft->getWidth(),  +										mArrowLeft->getHeight()); +			arrow_imagep = mArrowLeft; +			break; +		case BOTTOM: +			my_rect.setCenterAndSize(	target_rect.getCenterX(),  +										target_rect.mBottom - (my_local_rect.getHeight() / 2 + mDistance), +										my_local_rect.getWidth(),  +										my_local_rect.getHeight()); +			arrow_rect.setCenterAndSize(my_local_rect.getCenterX(), +										my_local_rect.mTop + mArrowUp->getHeight() / 2 + mArrowUpOffset, +										mArrowUp->getWidth(),  +										mArrowUp->getHeight()); +			arrow_imagep = mArrowUp; +			break; +		} +		setShape(my_rect); +		LLPanel::draw(); + +		arrow_imagep->draw(arrow_rect, LLColor4(1.f, 1.f, 1.f, alpha)); +	} +} + + +LLRegistry<std::string, LLHandle<LLView> > LLHints::sTargetRegistry; +std::map<LLNotificationPtr, class LLHintPopup*> LLHints::sHints; + +//static +void LLHints::show(LLNotificationPtr hint) +{ +	LLHintPopup::Params p; +	LLParamSDParser::instance().readSD(hint->getPayload(), p); + +	p.notification = hint; + +	LLHintPopup* popup = new LLHintPopup(p); +	 +	sHints[hint] = popup; + +	LLView* hint_holder = gViewerWindow->getHintHolder(); +	if (hint_holder) +	{ +		hint_holder->addChild(popup); +		popup->centerWithin(hint_holder->getLocalRect()); +	} +} + +void LLHints::hide(LLNotificationPtr hint) +{ +	hint_map_t::iterator found_it = sHints.find(hint); +	if (found_it != sHints.end()) +	{ +		found_it->second->hide(); +		sHints.erase(found_it); +	} +} + +//static +void LLHints::registerHintTarget(const std::string& name, LLHandle<LLView> target) +{ +	sTargetRegistry.defaultRegistrar().add(name, target); +} + +//static  +LLHandle<LLView> LLHints::getHintTarget(const std::string& name) +{ +	LLHandle<LLView>* handlep = sTargetRegistry.getValue(name); +	if (handlep)  +	{ +		return *handlep; +	} +	else +	{ +		return LLHandle<LLView>(); +	} +} diff --git a/indra/newview/llhints.h b/indra/newview/llhints.h new file mode 100644 index 0000000000..d2580df012 --- /dev/null +++ b/indra/newview/llhints.h @@ -0,0 +1,54 @@ +/** + * @file llhints.h + * @brief Hint popups for displaying context sensitive help in a UI overlay + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLHINTS_H +#define LL_LLHINTS_H + +#include "llpanel.h" +#include "llnotifications.h" + + +class LLHints +{ +public: +	static void show(LLNotificationPtr hint); +	static void hide(LLNotificationPtr hint); +	static void registerHintTarget(const std::string& name, LLHandle<LLView> target); +	static LLHandle<LLView> getHintTarget(const std::string& name); +private: +	static LLRegistry<std::string, LLHandle<LLView> > sTargetRegistry; +	typedef std::map<LLNotificationPtr, class LLHintPopup*> hint_map_t; +	static hint_map_t sHints; +}; + + +#endif diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index fc41137686..148a5786cb 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -45,7 +45,9 @@  #include "llvoavatarself.h" // to check gAgentAvatarp->isSitting()  #include "llbottomtray.h"  #include "llbutton.h" +#include "llfirstuse.h"  #include "llfloaterreg.h" +#include "llhints.h"  #include "lljoystickbutton.h"  #include "lluictrlfactory.h"  #include "llviewerwindow.h" @@ -167,6 +169,7 @@ void LLFloaterMove::setVisible(BOOL visible)  	if (visible)  	{ +		LLFirstUse::notMoving(false);  		// Attach the Stand/Stop Flying panel.  		LLPanelStandStopFlying* ssf_panel = LLPanelStandStopFlying::getInstance();  		ssf_panel->reparent(this); @@ -566,6 +569,11 @@ void LLPanelStandStopFlying::setStandStopFlyingMode(EStandStopFlyingMode mode)  {  	LLPanelStandStopFlying* panel = getInstance(); +	if (mode == SSFM_STAND) +	{ +		LLFirstUse::sit(); +		LLFirstUse::notMoving(false); +	}  	panel->mStandButton->setVisible(SSFM_STAND == mode);  	panel->mStopFlyingButton->setVisible(SSFM_STOP_FLYING == mode); @@ -596,6 +604,7 @@ BOOL LLPanelStandStopFlying::postBuild()  	mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this));  	mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance, TRUE));  	mStandButton->setVisible(FALSE); +	LLHints::registerHintTarget("stand_btn", mStandButton->getHandle());  	mStopFlyingButton = getChild<LLButton>("stop_fly_btn");  	//mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE)); diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 6cfd810c10..41a19a54a8 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -38,6 +38,7 @@  #include "llfloaterreg.h"  #include "lltrans.h" +#include "llfirstuse.h"  #include "llnearbychatbar.h"  #include "llbottomtray.h"  #include "llagent.h" @@ -490,6 +491,7 @@ BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::strin  void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata)  { +	LLFirstUse::otherAvatarChatFirst(false);  	LLNearbyChatBar* self = (LLNearbyChatBar *)userdata; diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 1fadb126e4..4011552112 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -37,6 +37,7 @@  #include "llbottomtray.h"  #include "llchatitemscontainerctrl.h" +#include "llfirstuse.h"  #include "llfloaterscriptdebug.h"  #include "llnearbychat.h"  #include "llrecentpeople.h" @@ -347,7 +348,13 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)  	if(chat_msg.mMuted == TRUE)  		return;  	if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull()) -         LLRecentPeople::instance().add(chat_msg.mFromID); +	{ +        LLRecentPeople::instance().add(chat_msg.mFromID); +		if (chat_msg.mFromID != gAgentID) +		{ +	 		LLFirstUse::otherAvatarChatFirst(); +		} +	}  	if(chat_msg.mText.empty())  		return;//don't process empty messages diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 99a1fedcf3..7b8f530178 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -269,6 +269,20 @@ protected:  	void onRejectToast(LLUUID& id);  }; +/** + * Handler for UI hints. + */ +class LLHintHandler : public LLSingleton<LLHintHandler> +{ +public: +	LLHintHandler(); +	virtual ~LLHintHandler(); + +	// base interface functions +	virtual bool processNotification(const LLSD& notify); +}; + +  class LLHandlerUtil  {  public: diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp new file mode 100644 index 0000000000..a9460821b0 --- /dev/null +++ b/indra/newview/llnotificationhinthandler.cpp @@ -0,0 +1,64 @@ +/** + * @file llnotificationhinthandler.cpp + * @brief Notification Handler Class for UI Hints + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" // must be first include + +#include "llnotificationhandler.h" +#include "llhints.h" +#include "llnotifications.h" + +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; +} diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 4401bb953f..86496c9d02 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -66,6 +66,7 @@ void LLNotificationManager::init()  	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"));  	LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));  	LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); @@ -74,6 +75,7 @@ void LLNotificationManager::init()  	LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));  	LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));  	LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); +	LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1));  	mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD()));  	mNotifyHandlers["notifytip"] =  boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 2302772803..155e000bb8 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -746,7 +746,7 @@ void LLPanelGroupGeneral::updateMembers()  		sSDTime += sd_timer.getElapsedTimeF32();  		element_timer.reset(); -		LLScrollListItem* member_row = mListVisibleMembers->addElement(row);//, ADD_SORTED); +		LLScrollListItem* member_row = mListVisibleMembers->addElement(row);  		if ( member->isOwner() )  		{ diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index 1404cfcea2..16d5f8140d 100644 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -528,7 +528,7 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)  			row["columns"][4]["column"] = "hidden";  			row["columns"][4]["value"] = hidden; -			mGroupParcelsp->addElement(row, ADD_SORTED); +			mGroupParcelsp->addElement(row);  		}  	}  } diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 7a28d10baf..efc797cfe9 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1631,7 +1631,7 @@ void LLPanelGroupMembersSubTab::updateMembers()  			row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();  			row["columns"][2]["font"] = "SANSSERIF_SMALL"; -			LLScrollListItem* member = mMembersList->addElement(row);//, ADD_SORTED); +			LLScrollListItem* member = mMembersList->addElement(row);  			LLUUID id = member->getUUID();  			mHasMatch = TRUE; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 4b23e63f12..58ed01896a 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -1110,9 +1110,10 @@ void LLPanelLogin::updateServerCombo()  	{  		if (!grid_choice->first.empty())  		{ -			server_choice_combo->add(grid_choice->second, grid_choice->first, ADD_SORTED); +			server_choice_combo->add(grid_choice->second, grid_choice->first);  		}  	} +	server_choice_combo->sortByName();  	server_choice_combo->addSeparator(ADD_TOP); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index abf2b94b09..c8a9176d92 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -42,6 +42,7 @@  #include "llcombobox.h"  #include "llfiltereditor.h" +#include "llfirstuse.h"  #include "llfloaterreg.h"  #include "llnotificationsutil.h"  #include "lltabcontainer.h" @@ -351,6 +352,8 @@ BOOL LLPanelPlaces::postBuild()  void LLPanelPlaces::onOpen(const LLSD& key)  { +	LLFirstUse::notUsingDestinationGuide(false); +  	if (!mPlaceProfile || !mLandmarkInfo)  		return; diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 9cc775d427..583b41aa57 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -1178,7 +1178,7 @@ void LLPanelPrimMediaControls::setCurrentURL()  //	if (media_address_combo && mCurrentURL != "about:blank")  //	{  //		media_address_combo->remove(mCurrentURL); -//		media_address_combo->add(mCurrentURL, ADD_SORTED); +//		media_address_combo->add(mCurrentURL);  //		media_address_combo->selectByValue(mCurrentURL);  //	}  #else   // USE_COMBO_BOX_FOR_MEDIA_URL diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 0951586dd5..f9189bfb22 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -36,6 +36,7 @@  #include "llappearancemgr.h"  #include "llavataractions.h"  #include "llbutton.h" +#include "llfirstuse.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llinventorypanel.h" @@ -128,6 +129,8 @@ BOOL LLSidepanelInventory::postBuild()  void LLSidepanelInventory::onOpen(const LLSD& key)  { +	LLFirstUse::inventoryOffer(false); +  	if(key.size() == 0)  		return; diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 7104f3934d..7cfc774883 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -37,6 +37,8 @@  #include "llagentcamera.h"  #include "llappviewer.h"  #include "llbottomtray.h" +#include "llfirstuse.h" +#include "llhints.h"  #include "llsidetray.h"  #include "llviewerwindow.h"  #include "llaccordionctrl.h" @@ -422,6 +424,7 @@ void	LLSideTray::createButtons	()  		{  			mCollapseButton = createButton("",sidebar_tab->mImage,sidebar_tab->getTabTitle(),  				boost::bind(&LLSideTray::onToggleCollapse, this)); +			LLHints::registerHintTarget("side_panel_btn", mCollapseButton->getHandle());  		}  		else  		{ @@ -430,6 +433,8 @@ void	LLSideTray::createButtons	()  			mTabButtons[name] = button;  		}  	} +	LLHints::registerHintTarget("inventory_btn", mTabButtons["sidebar_inventory"]->getHandle()); +	LLHints::registerHintTarget("dest_guide_btn", mTabButtons["sidebar_places"]->getHandle());  }  void		LLSideTray::processTriState () @@ -466,6 +471,7 @@ void		LLSideTray::onTabButtonClick(string name)  void		LLSideTray::onToggleCollapse()  { +	LLFirstUse::notUsingSidePanel(false);  	if(mCollapsed)  	{  		expandSideBar(); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index a6bb4d4d5f..6a081a573e 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -39,6 +39,7 @@  #include "llagentcamera.h"  #include "llbutton.h"  #include "llcommandhandler.h" +#include "llfirstuse.h"  #include "llviewercontrol.h"  #include "llfloaterbuycurrency.h"  #include "llbuycurrencyhtml.h" @@ -47,6 +48,7 @@  #include "llpanelvolumepulldown.h"  #include "llfloaterregioninfo.h"  #include "llfloaterscriptdebug.h" +#include "llhints.h"  #include "llhudicon.h"  #include "llnavigationbar.h"  #include "llkeyboard.h" @@ -191,6 +193,8 @@ BOOL LLStatusBar::postBuild()  	mMediaToggle->setClickedCallback( &LLStatusBar::onClickMediaToggle, this );  	mMediaToggle->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterNearbyMedia, this)); +	LLHints::registerHintTarget("linden_balance", getChild<LLView>("balance_bg")->getHandle()); +  	gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2));  	// Adding Net Stat Graph @@ -338,6 +342,11 @@ void LLStatusBar::creditBalance(S32 credit)  void LLStatusBar::setBalance(S32 balance)  { +	if (balance > getBalance() && getBalance() != 0) +	{ +		LLFirstUse::receiveLindens(); +	} +  	std::string money_str = LLResMgr::getInstance()->getMonetaryString( balance );  	LLTextBox* balance_box = getChild<LLTextBox>("balance"); @@ -460,6 +469,7 @@ void LLStatusBar::onClickBuyCurrency()  	// open a currency floater - actual one open depends on   	// value specified in settings.xml  	LLBuyCurrencyHTML::openCurrencyFloater(); +	LLFirstUse::receiveLindens(false);  }  void LLStatusBar::onMouseEnterVolume() diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 1f3785d733..d89ee13b95 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2826,25 +2826,18 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla  			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << plugin->getClickTarget() << "\", uri is " << plugin->getClickURL() << LL_ENDL;  			// retrieve the event parameters  			std::string url = plugin->getClickURL(); +			std::string target = plugin->getClickTarget();  			U32 target_type = plugin->getClickTargetType(); -			 +  			switch (target_type)  			{ -			case LLPluginClassMedia::TARGET_EXTERNAL: -				// force url to external browser -				LLWeb::loadURLExternal(url); -				break; -			case LLPluginClassMedia::TARGET_BLANK: -				// open in SL media browser or external browser based on user pref -				LLWeb::loadURL(url); -				break;  			case LLPluginClassMedia::TARGET_NONE:  				// ignore this click and let media plugin handle it  				break; -			case LLPluginClassMedia::TARGET_OTHER: -				LL_WARNS("LinkTarget") << "Unsupported link target type" << LL_ENDL; +			default: +				// loadURL now handles distinguishing between _blank, _external, and other named targets. +				LLWeb::loadURL(url, target);  				break; -			default: break;  			}  		};  		break; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a04c919310..9bb734a3d3 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -56,6 +56,7 @@  #include "llagentcamera.h"  #include "llcallingcard.h"  #include "llbuycurrencyhtml.h" +#include "llfirstuse.h"  #include "llfloaterbuyland.h"  #include "llfloaterland.h"  #include "llfloaterregioninfo.h" @@ -1763,6 +1764,8 @@ void inventory_offer_handler(LLOfferInfo* info)  		return;  	} +	LLFirstUse::inventoryOffer(); +  	// Avoid the Accept/Discard dialog if the user so desires. JC  	if (gSavedSettings.getBOOL("AutoAcceptNewInventory")  		&& (info->mType == LLAssetType::AT_NOTECARD diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b36af7d95b..cfb8b077e5 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -102,6 +102,7 @@  #include "llface.h"  #include "llfeaturemanager.h"  #include "llfilepicker.h" +#include "llfirstuse.h"  #include "llfloater.h"  #include "llfloaterbuildoptions.h"  #include "llfloaterbuyland.h" @@ -1529,6 +1530,7 @@ void LLViewerWindow::initBase()  	mNonSideTrayView = main_view->getChildView("non_side_tray_view")->getHandle();  	mFloaterViewHolder = main_view->getChildView("floater_view_holder")->getHandle();  	mPopupView = main_view->getChild<LLPopupView>("popup_holder"); +	mHintHolder = main_view->getChild<LLView>("hint_holder")->getHandle();  	// Constrain floaters to inside the menu and status bar regions.  	gFloaterView = main_view->getChild<LLFloaterView>("Floater View"); @@ -2422,6 +2424,18 @@ void LLViewerWindow::updateUI()  	static std::string last_handle_msg; +	if (gLoggedInTime.getStarted()) +	{ +		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("DestinationGuideHintTimeout")) +		{ +			LLFirstUse::notUsingDestinationGuide(); +		} +		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("SidePanelHintTimeout")) +		{ +			LLFirstUse::notUsingSidePanel(); +		} +	} +  	LLConsole::updateClass();  	// animate layout stacks so we have up to date rect for world view diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 1e0200a075..cd1ee8a5fd 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -294,6 +294,7 @@ public:  	void			updateWorldViewRect(bool use_full_window=false);  	LLView*			getNonSideTrayView() { return mNonSideTrayView.get(); }  	LLView*			getFloaterViewHolder() { return mFloaterViewHolder.get(); } +	LLView*			getHintHolder() { return mHintHolder.get(); }  	BOOL			handleKey(KEY key, MASK mask);  	void			handleScrollWheel	(S32 clicks); @@ -453,6 +454,7 @@ protected:  	LLHandle<LLView> mWorldViewPlaceholder;	// widget that spans the portion of screen dedicated to rendering the 3d world  	LLHandle<LLView> mNonSideTrayView;		// parent of world view + bottom bar, etc...everything but the side tray  	LLHandle<LLView> mFloaterViewHolder;	// container for floater_view +	LLHandle<LLView> mHintHolder;			// container for hints  	LLPopupView*	mPopupView;			// container for transient popups  	class LLDebugText* mDebugText; // Internal class for debug text diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 5c9633c036..b61109d490 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -84,23 +84,23 @@ void LLWeb::initClass()  // static -void LLWeb::loadURL(const std::string& url) +void LLWeb::loadURL(const std::string& url, const std::string& target)  { -	if (gSavedSettings.getBOOL("UseExternalBrowser")) +	if (gSavedSettings.getBOOL("UseExternalBrowser") || (target == "_external"))  	{  		loadURLExternal(url);  	}  	else  	{ -		loadURLInternal(url); +		loadURLInternal(url, target);  	}  }  // static -void LLWeb::loadURLInternal(const std::string &url) +void LLWeb::loadURLInternal(const std::string &url, const std::string& target)  { -	LLFloaterReg::showInstance("media_browser", url); +	LLFloaterMediaBrowser::create(url, target);  } diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h index 1119b80bb4..20c7391dbf 100644 --- a/indra/newview/llweb.h +++ b/indra/newview/llweb.h @@ -49,11 +49,14 @@ public:  	static void initClass();  	/// Load the given url in the user's preferred web browser -	static void loadURL(const std::string& url); +	static void loadURL(const std::string& url, const std::string& target); +	static void loadURL(const std::string& url) { loadURL(url, LLStringUtil::null); }  	/// Load the given url in the user's preferred web browser	 -	static void loadURL(const char* url) { loadURL( ll_safe_string(url) ); } +	static void loadURL(const char* url, const std::string& target) { loadURL( ll_safe_string(url), target); } +	static void loadURL(const char* url) { loadURL( ll_safe_string(url), LLStringUtil::null ); }  	/// Load the given url in the Second Life internal web browser -	static void loadURLInternal(const std::string &url); +	static void loadURLInternal(const std::string &url, const std::string& target); +	static void loadURLInternal(const std::string &url) { loadURLInternal(url, LLStringUtil::null); }  	/// Load the given url in the operating system's web browser, async if we want to return immediately  	/// before browser has spawned  	static void loadURLExternal(const std::string& url); diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 082b37d80b..9fbbfb1d2b 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -645,5 +645,11 @@ with the same filename but different name    <texture name="buy_off" file_name="widgets/buy_off.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>    <texture name="buy_over" file_name="widgets/buy_over.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>    <texture name="buy_press" file_name="widgets/buy_press.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/> -   + +  <texture name="hint_background" file_name="windows/hint_background.png" preload="false" scale.left="8" scale.top="70" scale.right="195" scale.bottom="11"/> +  <texture name="hint_arrow_left" file_name="windows/hint_arrow_left.png" preload="false"/> +  <texture name="hint_arrow_right" file_name="windows/hint_arrow_right.png" preload="false"/> +  <texture name="hint_arrow_up" file_name="windows/hint_arrow_up.png" preload="false"/> +  <texture name="hint_arrow_down" file_name="windows/hint_arrow_down.png" preload="false"/> +  </textures> diff --git a/indra/newview/skins/default/textures/windows/hint_arrow_down.png b/indra/newview/skins/default/textures/windows/hint_arrow_down.pngBinary files differ new file mode 100644 index 0000000000..11ab3c2d0c --- /dev/null +++ b/indra/newview/skins/default/textures/windows/hint_arrow_down.png diff --git a/indra/newview/skins/default/textures/windows/hint_arrow_left.png b/indra/newview/skins/default/textures/windows/hint_arrow_left.pngBinary files differ new file mode 100644 index 0000000000..e5c597a550 --- /dev/null +++ b/indra/newview/skins/default/textures/windows/hint_arrow_left.png diff --git a/indra/newview/skins/default/textures/windows/hint_arrow_right.png b/indra/newview/skins/default/textures/windows/hint_arrow_right.pngBinary files differ new file mode 100644 index 0000000000..3f89187e13 --- /dev/null +++ b/indra/newview/skins/default/textures/windows/hint_arrow_right.png diff --git a/indra/newview/skins/default/textures/windows/hint_arrow_up.png b/indra/newview/skins/default/textures/windows/hint_arrow_up.pngBinary files differ new file mode 100644 index 0000000000..1050097efb --- /dev/null +++ b/indra/newview/skins/default/textures/windows/hint_arrow_up.png diff --git a/indra/newview/skins/default/textures/windows/hint_background.png b/indra/newview/skins/default/textures/windows/hint_background.pngBinary files differ new file mode 100644 index 0000000000..0839a95205 --- /dev/null +++ b/indra/newview/skins/default/textures/windows/hint_background.png diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml index c02d607586..18f3b9ab06 100644 --- a/indra/newview/skins/default/xui/en/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml @@ -9,7 +9,7 @@   name="floater_about"   help_topic="floater_about"   save_rect="true" - single_instance="true" + auto_tile="true"   title="MEDIA BROWSER"   width="820">      <floater.string diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml index a1ca910cbb..0bf5717de8 100644 --- a/indra/newview/skins/default/xui/en/main_view.xml +++ b/indra/newview/skins/default/xui/en/main_view.xml @@ -208,6 +208,13 @@            bottom="-1"            height="11" />    </panel> +  <view top="0" +        left="0" +        width="1024" +        height="768" +        name="hint_holder" +        mouse_opaque="false" +        follows="all"/>    <menu_holder top="0"                 follows="all"                 height="768" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 609a9b09be..60b0b1e8dc 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6397,6 +6397,57 @@ Mute everyone?      <unique/>    </notification> +  <notification +  name="HintChat" +  label="Chat" +  type="hint"> +    To join the conversation, type into the chat field below. +  </notification> + +  <notification +  name="HintSit" +  label="Stand" +  type="hint"> +    To stand up and exit the sitting position, click the Stand button. +  </notification> +   +  <notification +  name="HintDestinationGuide" +  label="Explore the World" +  type="hint"> +    The Destination Guide contains thousands of new places to discover. Select a location and choose Teleport to start exploring. +  </notification> +   +  <notification +    name="HintSidePanel" +    label="Side Panel" +    type="hint"> +    Get quick access to your inventory, outfits, profiles and more in the side panel. +    <!--<unique/>--> +  </notification> + +  <notification +  name="HintMove" +  label="Move" +  type="hint"> +    To walk or run, open the Move Panel and use the directional arrows to navigate. You can also use the directional keys on your keyboard. +    <!--<unique/>--> +  </notification> + +  <notification +  name="HintInventory" +  label="Inventory" +  type="hint"> +    Check your inventory to find items. Newest items can be easily found in the Recent tab. +  </notification> + +  <notification +  name="HintLindenDollar" +  label="You've got Linden Dollars!" +  type="hint"> +    Here's your current balance of L$. Click Buy L$ to purchase more Linden Dollars. +  </notification> +    <global name="UnsupportedCPU">  - Your CPU speed does not meet the minimum requirements.    </global> diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index 76f7484c68..1e1d2d18ca 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -60,6 +60,8 @@       left="0"       right="-1"       top="0" +     sort_column="0" +     sort_ascending="true"       name="group_parcel_list"       width="313">          <scroll_list.columns diff --git a/indra/newview/skins/default/xui/en/panel_hint.xml b/indra/newview/skins/default/xui/en/panel_hint.xml new file mode 100644 index 0000000000..54ea08e5d4 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_hint.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="hint" + width="205" + height="100" + background_opaque="true" + background_visible="true" + layout="topleft"  + bg_opaque_image="hint_background"> +  <text name="hint_title" +        font="SansSerifMedium"  +        left="8" +        right="180" +        top="8" +        bottom="20" +        follows="left|right|top" +        text_color="White" +        wrap="false"/> +  <text name="hint_text" +        left="8" +        right="197" +        top="26" +        bottom="90" +        follows="all"  +        text_color="White" +        wrap="true"/> +  <button right="197"  +          top="8" +          width="16"  +          height="16" +          name="close"  +          follows="right|top"  +          image_unselected="Icon_Close_Foreground" +          image_selected="Icon_Close_Press"/> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml index 516457dd93..559df5bec9 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml @@ -57,6 +57,8 @@       left="10"       multi_select="true"       name="enabled_popups" +     sort_column="0" +     sort_ascending="true"        width="495" />  	 <button  	 enabled_control="FirstSelectedDisabledPopups" @@ -103,6 +105,8 @@       height="140"       layout="topleft"       left="10" +     sort_column="0" +     sort_ascending="true"       multi_select="true"       name="disabled_popups"       width="495" /> diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml index 9dff00fa0b..c5e8bf5803 100644 --- a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml +++ b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml @@ -79,6 +79,8 @@       layout="topleft"       left_delta="0"       multi_select="true" +     sort_column="0" +     sort_ascending="true"       name="scripts_list"       top_delta="16"       width="460"> diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index 7a544debb2..166905c37c 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -961,6 +961,23 @@ mediaPanel*  LLMediaPluginTest::findMediaPanel( LLPluginClassMedia* source )  ////////////////////////////////////////////////////////////////////////////////  // +mediaPanel* LLMediaPluginTest::findMediaPanel( const std::string &target_name ) +{ +	mediaPanel *result = NULL; + +	for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) +	{ +		if ( mMediaPanels[ panel ]->mTarget == target_name ) +		{ +			result = mMediaPanels[ panel ]; +		} +	} + +	return result; +} + +//////////////////////////////////////////////////////////////////////////////// +//  void LLMediaPluginTest::navigateToNewURI( std::string uri )  {  	if ( uri.length() ) @@ -1571,7 +1588,7 @@ std::string LLMediaPluginTest::pluginNameFromMimeType( std::string& mime_type )  ////////////////////////////////////////////////////////////////////////////////  // -void LLMediaPluginTest::addMediaPanel( std::string url ) +mediaPanel* LLMediaPluginTest::addMediaPanel( std::string url )  {  	// Get the plugin filename using the URL  	std::string mime_type = mimeTypeFromUrl( url ); @@ -1603,7 +1620,7 @@ void LLMediaPluginTest::addMediaPanel( std::string url )  	if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))  	{  		std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl; -		return; +		return NULL;  	}  	std::string user_data_path = std::string( cwd ) + "/";  #endif @@ -1673,6 +1690,8 @@ void LLMediaPluginTest::addMediaPanel( std::string url )  		std::cout << "Adding new media panel for " << url << "(" << media_width << "x" << media_height << ") with index " << panel->mId << " - total panels = " << mMediaPanels.size() << std::endl;  	} +	 +	return panel;  }  //////////////////////////////////////////////////////////////////////////////// @@ -1778,15 +1797,15 @@ void LLMediaPluginTest::updateMediaPanel( mediaPanel* panel )  ////////////////////////////////////////////////////////////////////////////////  // -void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url ) +mediaPanel* LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )  {  	// no media panels so we can't change anything - have to add  	if ( mMediaPanels.size() == 0 ) -		return; +		return NULL;  	// sanity check  	if ( ! panel ) -		return; +		return NULL;  	int index;  	for(index = 0; index < (int)mMediaPanels.size(); index++) @@ -1798,7 +1817,7 @@ void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )  	if(index >= (int)mMediaPanels.size())  	{  		// panel isn't in mMediaPanels -		return; +		return NULL;  	}  	std::cout << "Replacing media panel with index " << panel->mId << std::endl; @@ -1840,7 +1859,7 @@ void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )  	if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))  	{  		std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl; -		return; +		return NULL;  	}  	std::string user_data_path = std::string( cwd ) + "/";  #endif @@ -1880,6 +1899,8 @@ void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )  	// load and start the URL  	panel->mMediaSource->loadURI( url );  	panel->mMediaSource->start(); +	 +	return panel;  }  //////////////////////////////////////////////////////////////////////////////// @@ -2139,7 +2160,46 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e  		break;  		case MEDIA_EVENT_CLICK_LINK_HREF: -			std::cerr <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << std::endl; +		{ +			std::cerr <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << ", target is " << self->getClickTarget() << std::endl; +			// retrieve the event parameters +			std::string url = self->getClickURL(); +			std::string target = self->getClickTarget(); +			U32 target_type = self->getClickTargetType(); + +			switch (target_type) +			{ +				case LLPluginClassMedia::TARGET_NONE: +					// ignore this click +				break; +				 +				case LLPluginClassMedia::TARGET_EXTERNAL: +					// this should open in an external browser, but since this is a test app we don't care. +				break; +				 +				case LLPluginClassMedia::TARGET_BLANK: +					// Create a new panel with the specified URL. +					addMediaPanel(url); +				break; + +				case LLPluginClassMedia::TARGET_OTHER: +					mediaPanel *target_panel = findMediaPanel(target); +					if(target_panel) +					{ +						target_panel = replaceMediaPanel(target_panel, url); +					} +					else +					{ +						target_panel = addMediaPanel(url); +					} + +					if(target_panel) +					{ +						target_panel->mTarget = target; +					} +				break; +			} +		}  		break;  		case MEDIA_EVENT_CLICK_LINK_NOFOLLOW: diff --git a/indra/test_apps/llplugintest/llmediaplugintest.h b/indra/test_apps/llplugintest/llmediaplugintest.h index 5d08e42148..ecd6cbfc4f 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.h +++ b/indra/test_apps/llplugintest/llmediaplugintest.h @@ -56,6 +56,7 @@ struct mediaPanel  		int mId;  		std::string mStartUrl;  		std::string mMimeType; +		std::string mTarget;  		LLPluginClassMedia *mMediaSource;  		int mMediaWidth;  		int mMediaHeight; @@ -96,16 +97,17 @@ class LLMediaPluginTest : public LLPluginClassMediaOwner  		void draw( int draw_type );  		void windowPosToTexturePos( int window_x, int window_y, int& media_x, int& media_y, int& id ); -		void addMediaPanel( std::string url ); +		mediaPanel* addMediaPanel( std::string url );  		void updateMediaPanel( mediaPanel* panel );  		void remMediaPanel( mediaPanel* panel ); -		void replaceMediaPanel( mediaPanel* panel, std::string url ); +		mediaPanel* replaceMediaPanel( mediaPanel* panel, std::string url );  		void getRandomMediaSize( int& width, int& height, std::string mime_type );  		void navigateToNewURI( std::string uri );          void initUrlHistory( std::string uri );  		void selectPanelById( int id );  		void selectPanel( mediaPanel* panel );  		mediaPanel* findMediaPanel( LLPluginClassMedia* panel ); +		mediaPanel* findMediaPanel( const std::string &target_name );  		void makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels );  		void makeChrome();  		void resetView(); | 
