diff options
56 files changed, 1190 insertions, 163 deletions
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 46491d8a29..2c339f4a3f 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -83,6 +83,8 @@ public:  	virtual void onDockHidden();  	virtual void onDockShown(); +	LLDockControl* getDockControl(); +  private:  	/**  	 * Provides unique of dockable floater. @@ -92,7 +94,6 @@ private:  protected:  	void setDockControl(LLDockControl* dockControl); -	LLDockControl* getDockControl();  	const LLUIImagePtr& getDockTongue();  private: diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index 30a45bedc7..550955c4c5 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -76,6 +76,9 @@ public:  	// gets a rect that bounds possible positions for a dockable control (EXT-1111)  	void getAllowedRect(LLRect& rect); +	S32 getTongueWidth() { return mDockTongue->getWidth(); } +	S32 getTongueHeight() { return mDockTongue->getHeight(); } +  private:  	virtual void moveDockable();  private: diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 831ac66d06..64a4824a17 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -891,7 +891,13 @@ void LLFlatListView::setNoItemsCommentVisible(bool visible) const  			// We have to update child rect here because of issues with rect after reshaping while creating LLTextbox  			// It is possible to have invalid LLRect if Flat List is in LLAccordionTab  			LLRect comment_rect = getLocalRect(); -			comment_rect.stretch(-getBorderWidth()); + +			// To see comment correctly (EXT - 3244) in mNoItemsCommentTextbox we must get border width +			// of LLFlatListView (@see getBorderWidth()) and stretch mNoItemsCommentTextbox to this width +			// But getBorderWidth() returns 0 if LLFlatListView not visible. So we have to get border width +			// from 'scroll_border' +			LLViewBorder* scroll_border = getChild<LLViewBorder>("scroll border"); +			comment_rect.stretch(-scroll_border->getBorderWidth());  			mNoItemsCommentTextbox->setRect(comment_rect);  		}  		mNoItemsCommentTextbox->setVisible(visible); diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index e68affc36c..faf9ccbeb8 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1887,9 +1887,10 @@ void LLTextEditor::doDelete()  			removeChar();  		} -		onKeyStroke();  	} +	onKeyStroke(); +  	needsReflow();  } diff --git a/indra/lscript/lscript_export.h b/indra/lscript/lscript_export.h index d4626a8cd2..4c883582e2 100644 --- a/indra/lscript/lscript_export.h +++ b/indra/lscript/lscript_export.h @@ -35,6 +35,6 @@  #include "lscript_library.h" -extern LLScriptLibrary gScriptLibrary; +  #endif diff --git a/indra/lscript/lscript_library.h b/indra/lscript/lscript_library.h index 6728d70d0a..363d11f3aa 100644 --- a/indra/lscript/lscript_library.h +++ b/indra/lscript/lscript_library.h @@ -70,7 +70,7 @@ public:  	std::vector<LLScriptLibraryFunction>	mFunctions;  }; -extern LLScriptLibrary gScriptLibrary; +  class LLScriptLibData  { @@ -428,4 +428,6 @@ public:  }; +extern LLScriptLibrary gScriptLibrary; +  #endif diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 80a3977d02..289e900eaf 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5038,7 +5038,18 @@        <key>Type</key>        <string>S32</string>        <key>Value</key> -      <integer>35</integer> +      <integer>5</integer> +    </map> +    <key>NotificationChannelHeightRatio</key> +    <map> +      <key>Comment</key> +      <string>Notification channel and World View ratio(0.0 - always show 1 notification, 1.0 - max ratio).</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>F32</string> +      <key>Value</key> +      <real>0.5</real>      </map>      <key>OverflowToastHeight</key>      <map> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 508badcc6f..9a1b749ba7 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -78,6 +78,8 @@  #include "lllocationhistory.h"  #include "llfasttimerview.h"  #include "llvoicechannel.h" +#include "llsidetray.h" +  #include "llweb.h"  #include "llsecondlifeurls.h" @@ -2854,6 +2856,8 @@ void LLAppViewer::requestQuit()  		gFloaterView->closeAllChildren(true);  	} +	LLSideTray::getInstance()->notifyChildren(LLSD().with("request","quit")); +  	send_stats();  	gLogoutTimer.reset(); @@ -3758,6 +3762,13 @@ void LLAppViewer::idleShutdown()  	{  		return;  	} + +	if (LLSideTray::getInstance()->notifyChildren(LLSD().with("request","wait_quit"))) +	{ +		return; +	} + +  	// ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup()  	// *TODO: ugly diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 4b3b7a99d8..30967677e8 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -61,6 +61,7 @@ static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p");  static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group");  static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc");  static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script"); +static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer");  static const LLRect CHICLET_RECT(0, 25, 25, 0);  static const LLRect CHICLET_ICON_RECT(0, 22, 22, 0); @@ -78,29 +79,73 @@ boost::signals2::signal<LLChiclet* (const LLUUID&),  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// +/** + * Updates the Well's 'Lit' state to flash it when "new messages" are come. + * + * It gets callback which will be called 2*N times with passed period. See EXT-3147 + */ +class LLSysWellChiclet::FlashToLitTimer : public LLEventTimer +{ +public: +	typedef boost::function<void()> callback_t; +	FlashToLitTimer(S32 count, F32 period, callback_t cb) +		: LLEventTimer(period) +		, mCallback(cb) +		, mFlashCount(2 * count) +		, mCurrentFlashCount(0) +	{ +		mEventTimer.stop(); +	} + +	BOOL tick() +	{ +		mCallback(); + +		if (++mCurrentFlashCount == mFlashCount) mEventTimer.stop(); +		return FALSE; +	} + +	void flash() +	{ +		mCurrentFlashCount = 0; +		mEventTimer.start(); +	} + +private: +	callback_t		mCallback; +	S32 mFlashCount; +	S32 mCurrentFlashCount; +}; +  LLSysWellChiclet::Params::Params()  : button("button")  , unread_notifications("unread_notifications") +, max_displayed_count("max_displayed_count", 9) +, flash_to_lit_count("flash_to_lit_count", 3) +, flash_period("flash_period", 0.5F)  {  	button.name("button");  	button.tab_stop(FALSE);  	button.label(LLStringUtil::null); -  }  LLSysWellChiclet::LLSysWellChiclet(const Params& p)  : LLChiclet(p)  , mButton(NULL)  , mCounter(0) +, mMaxDisplayedCount(p.max_displayed_count) +, mFlashToLitTimer(NULL)  {  	LLButton::Params button_params = p.button;  	mButton = LLUICtrlFactory::create<LLButton>(button_params);  	addChild(mButton); + +	mFlashToLitTimer = new FlashToLitTimer(p.flash_to_lit_count, p.flash_period, boost::bind(&LLSysWellChiclet::changeLitState, this));  }  LLSysWellChiclet::~LLSysWellChiclet()  { - +	delete mFlashToLitTimer;  }  void LLSysWellChiclet::setCounter(S32 counter) @@ -108,11 +153,30 @@ void LLSysWellChiclet::setCounter(S32 counter)  	std::string s_count;  	if(counter != 0)  	{ -		s_count = llformat("%d", counter); +		static std::string more_messages_exist("+"); +		std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : ""); +		s_count = llformat("%d%s" +			, llmin(counter, mMaxDisplayedCount) +			, more_messages.c_str() +			);  	}  	mButton->setLabel(s_count); +	/* +	Emulate 4 states of button by background images, see detains in EXT-3147 +	xml attribute           Description +	image_unselected        "Unlit" - there are no new messages +	image_selected          "Unlit" + "Selected" - there are no new messages and the Well is open +	image_pressed           "Lit" - there are new messages +	image_pressed_selected  "Lit" + "Selected" - there are new messages and the Well is open +	*/ +	mButton->setForcePressedState(counter > 0); + +	if (mCounter == 0 && counter > 0) +	{ +		mFlashToLitTimer->flash(); +	}  	mCounter = counter;  } @@ -126,6 +190,14 @@ void LLSysWellChiclet::setToggleState(BOOL toggled) {  	mButton->setToggleState(toggled);  } +void LLSysWellChiclet::changeLitState() +{ +	static bool set_lit = false; + +	mButton->setForcePressedState(set_lit); + +	set_lit ^= true; +}  /************************************************************************/  /*               LLIMWellChiclet implementation                         */ @@ -939,12 +1011,34 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){  	}  } +void object_chiclet_callback(const LLSD& data) +{ +	LLUUID object_id = data["object_id"]; +	bool new_message = data["new_message"]; + +	std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(object_id); +	std::list<LLChiclet *>::iterator iter; +	for (iter = chiclets.begin(); iter != chiclets.end(); iter++) +	{ +		LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*iter); +		if (chiclet != NULL) +		{ +			if(data.has("unread")) +			{ +				chiclet->setCounter(data["unread"]); +			} +			chiclet->setShowNewMessagesIcon(new_message); +		} +	} +}  BOOL LLChicletPanel::postBuild()  {  	LLPanel::postBuild();  	LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1));  	LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1)); +	LLScriptFloaterManager::getInstance()->addNewObjectCallback(boost::bind(object_chiclet_callback, _1)); +	LLScriptFloaterManager::getInstance()->addToggleObjectFloaterCallback(boost::bind(object_chiclet_callback, _1));  	LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1));  	LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLChicletPanel::onCurrentVoiceChannelChanged, this, _1)); @@ -1545,6 +1639,11 @@ void LLScriptChiclet::setSessionId(const LLUUID& session_id)  	}  } +void LLScriptChiclet::setCounter(S32 counter) +{ +	setShowNewMessagesIcon( counter > 0 ); +} +  void LLScriptChiclet::onMouseDown()  {  	LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId()); @@ -1601,6 +1700,11 @@ void LLInvOfferChiclet::setSessionId(const LLUUID& session_id)  	}  } +void LLInvOfferChiclet::setCounter(S32 counter) +{ +	setShowNewMessagesIcon( counter > 0 ); +} +  void LLInvOfferChiclet::onMouseDown()  {  	LLScriptFloaterManager::instance().toggleScriptFloater(getSessionId()); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 609ce16713..65abcd1f5f 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -315,7 +315,7 @@ public:  	{  		Optional<std::string> new_messages_icon_name; -		Params() : new_messages_icon_name("new_messages_icon_name", "icn_voice-localchat.tga") +		Params() : new_messages_icon_name("new_messages_icon_name", "Unread_IM")  		{}  	}; @@ -389,7 +389,7 @@ public:  	 * Made public so that it can be triggered from outside  	 * (more specifically, from the Active IM window).  	 */ -	void onMouseDown(); +	virtual void onMouseDown();  protected: @@ -594,7 +594,7 @@ public:  	/*virtual*/ void setSessionId(const LLUUID& session_id); -	/*virtual*/ void setCounter(S32 counter){} +	/*virtual*/ void setCounter(S32 counter);  	/*virtual*/ S32 getCounter() { return 0; } @@ -634,7 +634,7 @@ public:  	/*virtual*/ void setSessionId(const LLUUID& session_id); -	/*virtual*/ void setCounter(S32 counter){} +	/*virtual*/ void setCounter(S32 counter);  	/*virtual*/ S32 getCounter() { return 0; } @@ -745,7 +745,7 @@ private:  /**   * Implements notification chiclet. Used to display total amount of unread messages  - * across all IM sessions, total amount of system notifications. + * across all IM sessions, total amount of system notifications. See EXT-3147 for details   */  class LLSysWellChiclet : public LLChiclet  { @@ -757,6 +757,24 @@ public:  		Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; +		/** +		 * Contains maximum displayed count of unread messages. Default value is 9. +		 * +		 * If count is less than "max_unread_count" will be displayed as is. +		 * Otherwise 9+ will be shown (for default value). +		 */ +		Optional<S32> max_displayed_count; + +		/** +		 * How many time chiclet should flash before set "Lit" state. Default value is 3. +		 */ +		Optional<S32> flash_to_lit_count; + +		/** +		 * Period of flashing while setting "Lit" state, in seconds. Default value is 0.5. +		 */ +		Optional<F32> flash_period; +  		Params();  	}; @@ -778,9 +796,26 @@ protected:  	LLSysWellChiclet(const Params& p);  	friend class LLUICtrlFactory; +	/** +	 * Change Well 'Lit' state from 'Lit' to 'Unlit' and vice-versa. +	 * +	 * There is an assumption that it will be called 2*N times to do not change its start state. +	 * @see FlashToLitTimer +	 */ +	void changeLitState(); +  protected: +	class FlashToLitTimer;  	LLButton* mButton;  	S32 mCounter; +	S32 mMaxDisplayedCount; + +	/** +	 * How many times Well will blink. +	 */ +	S32 mFlashToLitCount; +	FlashToLitTimer* mFlashToLitTimer; +  };  /** diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 57bb93d81a..b9e0f928f1 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -41,6 +41,7 @@  // project include  #include "llagent.h" +#include "llappviewer.h"  #include "llbutton.h"  #include "llcheckboxctrl.h"  #include "llcombobox.h" @@ -142,6 +143,10 @@ BOOL LLFloaterChat::postBuild()  void LLFloaterChat::updateConsoleVisibility()  { +	if(gDisconnected) +	{ +		return; +	}  	// determine whether we should show console due to not being visible  	gConsole->setVisible( !isInVisibleChain()								// are we not in part of UI being drawn?  							|| isMinimized()								// are we minimized? diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 2bc07d0c27..47a168e354 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -90,8 +90,20 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  		case IM_SESSION_CONFERENCE_START:  			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);  			break; -		default: +		case IM_SESSION_GROUP_START:  			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); +			break; +		case IM_SESSION_INVITE:		 +			if (gAgent.isInGroup(mSessionID)) +			{ +				mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); +			} +			else +			{ +				mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); +			} +			break; +		default: break;  		}  	}  } @@ -415,6 +427,7 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock)  	if(channel)  	{  		channel->updateShowToastsState(); +		channel->redrawToasts();  	}  } @@ -439,6 +452,7 @@ void LLIMFloater::setVisible(BOOL visible)  	if(channel)  	{  		channel->updateShowToastsState(); +		channel->redrawToasts();  	}  	if (visible && mChatHistory && mInputEditor) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4780b51c55..4d2ba16a4c 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -88,6 +88,9 @@ const static std::string IM_TEXT("message");  const static std::string IM_FROM("from");  const static std::string IM_FROM_ID("from_id"); +const static std::string NO_SESSION("(IM Session Doesn't Exist)"); +const static std::string ADHOC_NAME_SUFFIX(" Conference"); +  std::string LLCallDialogManager::sPreviousSessionlName = "";  std::string LLCallDialogManager::sCurrentSessionlName = "";  LLIMModel::LLIMSession* LLCallDialogManager::sSession = NULL; @@ -116,6 +119,13 @@ void toast_callback(const LLSD& msg){  		return;  	} +	// Skip toasting if we have open window of IM with this session id +	LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]); +	if (open_im_floater && open_im_floater->getVisible()) +	{ +		return; +	} +  	LLSD args;  	args["MESSAGE"] = msg["message"];  	args["TIME"] = msg["time"]; @@ -154,7 +164,6 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&  	mInitialTargetIDs(ids),  	mVoiceChannel(NULL),  	mSpeakers(NULL), -	mCallDialogManager(NULL),  	mSessionInitialized(false),  	mCallBackEnabled(true),  	mTextIMPossible(true), @@ -288,9 +297,6 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  LLIMModel::LLIMSession::~LLIMSession()  { -	delete mCallDialogManager; -	mCallDialogManager = NULL; -  	delete mSpeakers;  	mSpeakers = NULL; @@ -455,10 +461,16 @@ void LLIMModel::testMessages()  	addMessage(bot2_session_id, from, bot2_id, "Test Message: OMGWTFBBQ.");  } - +//session name should not be empty  bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,   						   const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)  { +	if (name.empty()) +	{ +		llwarns << "Attempt to create a new session with empty name; id = " << session_id << llendl; +		return false; +	} +  	if (findIMSession(session_id))  	{  		llwarns << "IM Session " << session_id << " already exists" << llendl; @@ -615,7 +627,7 @@ const std::string& LLIMModel::getName(const LLUUID& session_id) const  	if (!session)   	{  		llwarns << "session " << session_id << "does not exist " << llendl; -		return LLStringUtil::null; +		return NO_SESSION;  	}  	return session->mName; @@ -1074,7 +1086,7 @@ public:  			if ( 404 == statusNum )  			{  				std::string error_string; -				error_string = "does not exist"; +				error_string = "session_does_not_exist_error";  				gIMMgr->showSessionStartError(error_string, mSessionID);  			}  		} @@ -1263,6 +1275,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat  {  	LLSD mCallDialogPayload;  	LLOutgoingCallDialog* ocd; +	bool is_incoming;  	mCallDialogPayload["session_id"] = sSession->mSessionID;  	mCallDialogPayload["session_name"] = sSession->mName; @@ -1272,8 +1285,10 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat  	switch(new_state)  	{			  	case LLVoiceChannel::STATE_CALL_STARTED : -		// do not show "Calling to..." if it is incoming P2P call -		if(sSession->mSessionType == LLIMModel::LLIMSession::P2P_SESSION && static_cast<LLVoiceChannelP2P*>(sSession->mVoiceChannel)->isIncomingCall()) +		// do not show "Calling to..." if it is incoming call +		is_incoming = LLVoiceClient::getInstance()->isSessionIncoming(sSession->mSessionID); +		// *TODO: implement for AdHoc and Group voice chats +		if(is_incoming)  		{  			return;  		} @@ -1285,6 +1300,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat  			ocd->getChild<LLTextBox>("leaving")->setVisible(true);  			ocd->getChild<LLTextBox>("connecting")->setVisible(false);  			ocd->getChild<LLTextBox>("noanswer")->setVisible(false); +			ocd->getChild<LLButton>("Cancel")->setVisible(true);  		}  		return; @@ -1296,10 +1312,12 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat  			ocd->getChild<LLTextBox>("leaving")->setVisible(true);  			ocd->getChild<LLTextBox>("connecting")->setVisible(true);  			ocd->getChild<LLTextBox>("noanswer")->setVisible(false); +			ocd->getChild<LLButton>("Cancel")->setVisible(true);  		}  		return;  	case LLVoiceChannel::STATE_ERROR : +		mCallDialogPayload["start_timer"] = true;  		ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE));  		if (ocd)  		{ @@ -1307,6 +1325,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat  			ocd->getChild<LLTextBox>("leaving")->setVisible(false);  			ocd->getChild<LLTextBox>("connecting")->setVisible(false);  			ocd->getChild<LLTextBox>("noanswer")->setVisible(true); +			ocd->getChild<LLButton>("Cancel")->setVisible(false);  		}  		return; @@ -1358,6 +1377,33 @@ LLCallDialog(payload)  		instance->onCancel(instance);  	}	  } +void LLOutgoingCallDialog::draw() +{ +	if (lifetimeHasExpired()) +	{ +		onLifetimeExpired(); +	} +	LLDockableFloater::draw(); +} + +bool LLOutgoingCallDialog::lifetimeHasExpired() +{ +	if (mLifetimeTimer.getStarted()) +	{ +		F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32(); +		if (elapsed_time > LIFETIME)  +		{ +			return true; +		} +	} +	return false; +} + +void LLOutgoingCallDialog::onLifetimeExpired() +{ +	mLifetimeTimer.stop(); +	closeFloater(); +}  void LLOutgoingCallDialog::onOpen(const LLSD& key)  { @@ -1386,6 +1432,13 @@ void LLOutgoingCallDialog::onOpen(const LLSD& key)  	childSetTextArg("connecting", "[CALLEE_NAME]", callee_name);  	LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");  	icon->setValue(callee_id); + +	// stop timer by default +	mLifetimeTimer.stop(); +	if(mPayload.has("start_timer")) +	{ +		mLifetimeTimer.reset(); +	}  } @@ -1509,6 +1562,8 @@ void LLIncomingCallDialog::processCallResponse(S32 response)  		return;  	LLUUID session_id = mPayload["session_id"].asUUID(); +	LLUUID caller_id = mPayload["caller_id"].asUUID(); +	std::string session_name = mPayload["session_name"].asString();  	EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger();  	LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)mPayload["inv_type"].asInteger();  	bool voice = true; @@ -1525,8 +1580,8 @@ void LLIncomingCallDialog::processCallResponse(S32 response)  		{  			// create a normal IM session  			session_id = gIMMgr->addP2PSession( -				mPayload["session_name"].asString(), -				mPayload["caller_id"].asUUID(), +				session_name, +				caller_id,  				mPayload["session_handle"].asString(),  				mPayload["session_uri"].asString()); @@ -1544,10 +1599,38 @@ void LLIncomingCallDialog::processCallResponse(S32 response)  		}  		else  		{ -			LLUUID new_session_id = gIMMgr->addSession( -				mPayload["session_name"].asString(), -				type, -				session_id); +			//session name should not be empty, but it can contain spaces so we don't trim +			std::string correct_session_name = session_name; +			if (session_name.empty()) +			{ +				llwarns << "Received an empty session name from a server" << llendl; +				 +				switch(type){ +				case IM_SESSION_CONFERENCE_START: +				case IM_SESSION_GROUP_START: +				case IM_SESSION_INVITE:		 +					if (gAgent.isInGroup(session_id)) +					{ +						LLGroupData data; +						if (!gAgent.getGroupData(session_id, data)) break; +						correct_session_name = data.mName; +					} +					else +					{ +						if (gCacheName->getFullName(caller_id, correct_session_name)) +						{ +							correct_session_name.append(ADHOC_NAME_SUFFIX);  +						} +					} +					llinfos << "Corrected session name is " << correct_session_name << llendl;  +					break; +				default:  +					llwarning("Received an empty session name from a server and failed to generate a new proper session name", 0); +					break; +				} +			} +			 +			LLUUID new_session_id = gIMMgr->addSession(correct_session_name, type, session_id);  			if (new_session_id != LLUUID::null)  			{  				LLIMFloater::show(new_session_id); @@ -1983,6 +2066,12 @@ LLUUID LLIMMgr::addSession(  		return LLUUID::null;  	} +	if (name.empty()) +	{ +		llwarning("Session name cannot be null!", 0); +		return LLUUID::null; +	} +  	LLUUID session_id = computeSessionID(dialog,other_participant_id);  	bool new_session = !LLIMModel::getInstance()->findIMSession(session_id); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index c2288a719a..f26889ac91 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -81,7 +81,6 @@ public:  		SType mSessionType;  		LLUUID mOtherParticipantID;  		std::vector<LLUUID> mInitialTargetIDs; -		LLCallDialogManager* mCallDialogManager;  		// connection to voice channel state change signal  		boost::signals2::connection mVoiceChannelStateChangeConnection; @@ -142,6 +141,7 @@ public:  	/**  	 * Create new session object in a model +	 * @param name session name should not be empty, will return false if empty  	 */  	bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id,   		const std::vector<LLUUID>& ids = std::vector<LLUUID>()); @@ -297,6 +297,7 @@ public:  	/**  	 * Creates a P2P session with the requisite handle for responding to voice calls.  	 *  +	 * @param name session name, cannot be null  	 * @param caller_uri - sip URI of caller. It should be always be passed into the method to avoid  	 * incorrect working of LLVoiceChannel instances. See EXT-2985.  	 */	 @@ -494,7 +495,16 @@ public:  	static void onCancel(void* user_data); +	// check timer state +	/*virtual*/ void draw(); +  private: +	// lifetime timer for NO_ANSWER notification +	LLTimer	mLifetimeTimer; +	// lifetime duration for NO_ANSWER notification +	static const S32 LIFETIME = 5; +	bool lifetimeHasExpired(); +	void onLifetimeExpired();  };  // Globals diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 5c240aa54a..83a8dcd9f0 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -266,6 +266,11 @@ public:  	static bool canLogToIM(const LLNotificationPtr& notification);  	/** +	 * Checks sufficient conditions to log notification message to nearby chat session. +	 */ +	static bool canLogToNearbyChat(const LLNotificationPtr& notification); + +	/**  	 * Checks sufficient conditions to spawn IM session.  	 */  	static bool canSpawnIMSession(const LLNotificationPtr& notification); @@ -287,6 +292,11 @@ public:  	 * Writes group notice notification message to IM  group session.  	 */  	static void logGroupNoticeToIMGroup(const LLNotificationPtr& notification); + +	/** +	 * Writes notification message to nearby chat. +	 */ +	static void logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type);  };  } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 6748bd7982..5b54092c5c 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -37,6 +37,8 @@  #include "llnotifications.h"  #include "llimview.h"  #include "llagent.h" +#include "llfloaterreg.h" +#include "llnearbychat.h"  using namespace LLNotificationsUI; @@ -47,7 +49,9 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),  						ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"),  						USER_GIVE_ITEM("UserGiveItem"), OFFER_FRIENDSHIP("OfferFriendship"),  						FRIENDSHIP_ACCEPTED("FriendshipAccepted"), -						FRIENDSHIP_OFFERED("FriendshipOffered"); +						FRIENDSHIP_OFFERED("FriendshipOffered"), +						FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), +						SERVER_OBJECT_MESSAGE("ServerObjectMessage");  // static  bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) @@ -55,7 +59,16 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)  	return GRANTED_MODIFY_RIGHTS == notification->getName()  			|| REVOKED_MODIFY_RIGHTS == notification->getName()  			|| PAYMENT_RECIVED == notification->getName() -			|| FRIENDSHIP_OFFERED == notification->getName(); +			|| FRIENDSHIP_OFFERED == notification->getName() +			|| SERVER_OBJECT_MESSAGE == notification->getName(); +} + +// static +bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) +{ +	return notification->getType() == "notifytip" +			&&  FRIEND_ONLINE != notification->getName() +			&& FRIEND_OFFLINE != notification->getName();  }  // static @@ -144,3 +157,15 @@ void LLHandlerUtil::logGroupNoticeToIMGroup(  			payload["group_id"], sender_id);  } +// static +void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type) +{ +	LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); +	if(nearby_chat) +	{ +		LLChat chat_msg(notification->getMessage()); +		chat_msg.mSourceType = type; +		nearby_chat->addMessage(chat_msg); +	} +} + diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 95f5ec801c..9afaddae82 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -88,18 +88,17 @@ bool LLTipHandler::processNotification(const LLSD& notify)  	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")  	{  		// archive message in nearby chat -		LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); -		if(nearby_chat) +		if (LLHandlerUtil::canLogToNearbyChat(notification))  		{ -			LLChat chat_msg(notification->getMessage()); -			chat_msg.mSourceType = CHAT_SOURCE_SYSTEM; -			nearby_chat->addMessage(chat_msg); +			LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM);  			// don't show toast if Nearby Chat is opened +			LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance< +					LLNearbyChat>("nearby_chat", LLSD());  			if (nearby_chat->getVisible())  			{  				return true; -			}			 +			}  		}  		LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index eb9cb10d56..b9f422ca6f 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -51,6 +51,7 @@  #include "llfloaterworldmap.h"  #include "llfloaterreg.h"  #include "llnotificationsutil.h" +#include "llvoiceclient.h"  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLDropTarget @@ -395,6 +396,7 @@ void LLPanelProfileTab::updateButtons()  					&& gAgent.isGodlike() || is_agent_mappable(getAvatarId());  	childSetEnabled("show_on_map_btn", enable_map_btn); +	childSetEnabled("call", LLVoiceClient::voiceEnabled());  }  ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 2cb3967685..e0f159cfeb 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -90,6 +90,7 @@ LLPanelGroup::LLPanelGroup()  :	LLPanel(),  	LLGroupMgrObserver( LLUUID() ),  	mAllowEdit( TRUE ) +	,mShowingNotifyDialog(false)  {  	// Set up the factory callbacks.  	// Roles sub tabs @@ -538,3 +539,69 @@ void LLPanelGroup::showNotice(const std::string& subject,  } +bool	LLPanelGroup::canClose() +{ +	if(getVisible() == false) +		return true; + +	bool need_save = false; +	std::string mesg; +	for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it) +		if(need_save|=(*it)->needsApply(mesg)) +			break; +	if(!need_save) +		return false; +	// If no message was provided, give a generic one.
 +	if (mesg.empty())
 +	{
 +		mesg = mDefaultNeedsApplyMesg;
 +	}
 +	// Create a notify box, telling the user about the unapplied tab.
 +	LLSD args;
 +	args["NEEDS_APPLY_MESSAGE"] = mesg;
 +	args["WANT_APPLY_MESSAGE"] = mWantApplyMesg;
 +
 +	LLNotificationsUtil::add("SaveChanges", args, LLSD(), boost::bind(&LLPanelGroup::handleNotifyCallback,this, _1, _2));
 +
 +	mShowingNotifyDialog = true;
 +
 +	return false;
 +} + +bool	LLPanelGroup::notifyChildren(const LLSD& info) +{ +	if(info.has("request") && mID.isNull() ) +	{ +		std::string str_action = info["request"]; + +		if (str_action == "quit" ) +		{ +			canClose();
 +			return true;
 +		} +		if(str_action == "wait_quit") +			return mShowingNotifyDialog; +	} +	return false; +} +bool LLPanelGroup::handleNotifyCallback(const LLSD& notification, const LLSD& response)
 +{
 +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 +	mShowingNotifyDialog = false;
 +	switch (option)
 +	{
 +	case 0: // "Apply Changes"
 +		apply();
 +		break;
 +	case 1: // "Ignore Changes"
 +		break;
 +	case 2: // "Cancel"
 +	default:
 +		// Do nothing.  The user is canceling the action.
 +		// If we were quitting, we didn't really mean it.
 +		LLAppViewer::instance()->abortQuit();
 +		break;
 +	}
 +	return false;
 +}
 + diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index 306e6575fc..f6aefdb676 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -89,7 +89,10 @@ public:  						   const std::string& inventory_name,  						   LLOfferInfo* inventory_offer); -	 + +	bool	notifyChildren		(const LLSD& info); +	bool	handleNotifyCallback(const LLSD&, const LLSD&); +  protected:  	virtual void update(LLGroupChange gc); @@ -107,6 +110,9 @@ protected:  protected:  	bool	apply(LLPanelGroupTab* tab); +	bool	canClose(); + +	bool	mShowingNotifyDialog;  	LLTimer mRefreshTimer; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index c85fab2092..32c9faa688 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -66,6 +66,30 @@ static const std::string TRASH_BUTTON_NAME = "trash_btn";  // helper functions  static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string); +static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list); + +/** + * Bridge to support knowing when the inventory has changed to update folder (open/close) state  + * for landmarks panels. + * + * Due to Inventory data are loaded in background we need to save folder state each time  + * next level is loaded. See EXT-3094. + */ +class LLLandmarksPanelObserver : public LLInventoryObserver +{ +public: +	LLLandmarksPanelObserver(LLLandmarksPanel* lp) : mLP(lp) {} +	virtual ~LLLandmarksPanelObserver() {} +	/*virtual*/ void changed(U32 mask); + +private: +	LLLandmarksPanel* mLP; +}; + +void LLLandmarksPanelObserver::changed(U32 mask) +{ +	mLP->saveFolderStateIfNoFilter(); +}  LLLandmarksPanel::LLLandmarksPanel()  	:	LLPanelPlacesTab() @@ -78,11 +102,18 @@ LLLandmarksPanel::LLLandmarksPanel()  	,	mGearFolderMenu(NULL)  	,	mGearLandmarkMenu(NULL)  { +	mInventoryObserver = new LLLandmarksPanelObserver(this); +	gInventory.addObserver(mInventoryObserver); +  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");  }  LLLandmarksPanel::~LLLandmarksPanel()  { +	if (gInventory.containsObserver(mInventoryObserver)) +	{ +		gInventory.removeObserver(mInventoryObserver); +	}  }  BOOL LLLandmarksPanel::postBuild() @@ -226,6 +257,14 @@ void LLLandmarksPanel::onSelectorButtonClicked()  	}  } +void LLLandmarksPanel::saveFolderStateIfNoFilter() +{ +	save_folder_state_if_no_filter(mFavoritesInventoryPanel); +	save_folder_state_if_no_filter(mLandmarksInventoryPanel); +	save_folder_state_if_no_filter(mMyInventoryPanel); +	save_folder_state_if_no_filter(mLibraryInventoryPanel); +} +  //////////////////////////////////////////////////////////////////////////  // PROTECTED METHODS  ////////////////////////////////////////////////////////////////////////// @@ -743,7 +782,7 @@ void LLLandmarksPanel::updateFilteredAccordions()  {  	LLInventoryPanel* inventory_list = NULL;  	LLAccordionCtrlTab* accordion_tab = NULL; -//	bool needs_arrange = false; +	bool needs_arrange = false;  	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)  	{ @@ -755,7 +794,7 @@ void LLLandmarksPanel::updateFilteredAccordions()  		if (NULL == inventory_list) continue;  		// This doesn't seem to work correctly.  Disabling for now. -Seraph -		/* +		// Enabled to show/hide accordions with/without landmarks. See EXT-2346. (Seth PE)  		LLFolderView* fv = inventory_list->getRootFolder();  		// arrange folder view contents to draw its descendants if it has any @@ -766,17 +805,17 @@ void LLLandmarksPanel::updateFilteredAccordions()  			needs_arrange = true;  		accordion_tab->setVisible(has_descendants); -		*/ -		accordion_tab->setVisible(TRUE); + +		//accordion_tab->setVisible(TRUE);  	}  	// we have to arrange accordion tabs for cases when filter string is less restrictive but  	// all items are still filtered. -//	if (needs_arrange) -//	{ +	if (needs_arrange) +	{  		static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");  		accordion->arrange(); -//	} +	}  }  /* @@ -1010,4 +1049,13 @@ static void filter_list(LLInventorySubTreePanel* inventory_list, const std::stri  	inventory_list->setFilterSubString(string);  } + +static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list) +{ +	// save current folder open state if no filter currently applied +	if (inventory_list->getRootFolder() && inventory_list->getRootFolder()->getFilterSubString().empty()) +	{ +		// inventory_list->saveFolderState(); // *TODO: commented out to fix build +	} +}  // EOF diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index bee141d051..b0e537f647 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -67,6 +67,11 @@ public:  		mCurrentSelectedList = inventory_list;  	} +	/** +	 * Saves folder state for all Inventory Panels if there are no applied filter. +	 */ +	void saveFolderStateIfNoFilter(); +  protected:  	/**  	 * @return true - if current selected panel is not null and selected item is a landmark @@ -151,6 +156,7 @@ private:  	LLMenuGL*					mGearFolderMenu;  	LLMenuGL*					mMenuAdd;  	LLInventorySubTreePanel*	mCurrentSelectedList; +	LLInventoryObserver*		mInventoryObserver;  	LLPanel*					mListCommands;  	bool 						mSortByDate; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 1e4682701e..5fb7dab7be 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -775,7 +775,7 @@ void LLPanelPeople::updateButtons()  	buttonSetEnabled("teleport_btn",		friends_tab_active && item_selected && isFriendOnline(selected_uuids.front()));  	buttonSetEnabled("view_profile_btn",	item_selected);  	buttonSetEnabled("im_btn",				multiple_selected); // allow starting the friends conference for multiple selection -	buttonSetEnabled("call_btn",			multiple_selected); +	buttonSetEnabled("call_btn",			multiple_selected && LLVoiceClient::voiceEnabled());  	buttonSetEnabled("share_btn",			item_selected); // not implemented yet  	bool none_group_selected = item_selected && selected_id.isNull(); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 57f3d86d53..04fe42de9f 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -100,7 +100,7 @@ LLContextMenu* NearbyMenu::createMenu()  		registrar.add("Avatar.Call",			boost::bind(&LLAvatarActions::startCall,				id));  		registrar.add("Avatar.OfferTeleport",	boost::bind(&NearbyMenu::offerTeleport,					this));  		registrar.add("Avatar.ShowOnMap",		boost::bind(&LLAvatarActions::startIM,					id));	// *TODO: unimplemented -		registrar.add("Avatar.Share",			boost::bind(&LLAvatarActions::startIM,					id));	// *TODO: unimplemented +		registrar.add("Avatar.Share",			boost::bind(&LLAvatarActions::share,					id));  		registrar.add("Avatar.Pay",				boost::bind(&LLAvatarActions::pay,						id));  		registrar.add("Avatar.BlockUnblock",	boost::bind(&LLAvatarActions::toggleBlock,				id)); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index f7f3c5830d..4a554c1b2c 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -854,6 +854,7 @@ void LLPanelPlaces::updateVerbs()  	mCancelBtn->setVisible(isLandmarkEditModeOn);  	mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn); +	mShowOnMapBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn);  	mOverflowBtn->setEnabled(is_place_info_visible && !is_create_landmark_visible);  	if (is_place_info_visible) diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 13f195a1be..48a7a32a3b 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -278,6 +278,16 @@ void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_lis  //  bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)  { +	/** +	 * We need to filter speaking objects. These objects shouldn't appear in the list +	 * @c LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy +	 */ +	const LLUUID& speaker_id = event->getValue().asUUID(); +	LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id); +	if(speaker.isNull() || speaker->mType == LLSpeaker::SPEAKER_OBJECT) +	{ +		return false; +	}  	return mParent.onAddItemEvent(event, userdata);  } @@ -314,6 +324,8 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  	registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2));  	registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2)); +	registrar.add("ParticipantList.ModerateVoice", boost::bind(&LLParticipantList::LLParticipantListMenu::moderateVoice, this, _2)); +  	enable_registrar.add("ParticipantList.EnableItem", boost::bind(&LLParticipantList::LLParticipantListMenu::enableContextMenuItem,	this, _2));  	enable_registrar.add("ParticipantList.CheckItem",  boost::bind(&LLParticipantList::LLParticipantListMenu::checkContextMenuItem,	this, _2)); @@ -322,6 +334,28 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  		"menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());  } +void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y) +{ +	LLPanelPeopleMenus::ContextMenu::show(spawning_view, uuids, x, y); + +	if (uuids.size() == 0) return; + +	const LLUUID speaker_id = mUUIDs.front(); +	BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, LLMute::flagVoiceChat); + +	if (is_muted) +	{ +		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteSelected", false); +		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteOthers", false); +	} +	else +	{ +		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false); +		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false); +	} + +} +  void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata)  {  	const LLUUID speaker_id = mUUIDs.front(); @@ -379,10 +413,10 @@ void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& u  		new MuteTextResponder(mParent.mSpeakerMgr->getSessionID()));  } -void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userdata) +void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, U32 flags)  {  	const LLUUID speaker_id = mUUIDs.front(); -	BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, LLMute::flagTextChat); +	BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, flags);  	std::string name;  	//fill in name using voice client's copy of name cache @@ -398,12 +432,54 @@ void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userda  	if (!is_muted)  	{ -		LLMuteList::getInstance()->add(mute, LLMute::flagTextChat); +		LLMuteList::getInstance()->add(mute, flags);  	}  	else  	{ -		LLMuteList::getInstance()->remove(mute, LLMute::flagTextChat); +		LLMuteList::getInstance()->remove(mute, flags); +	} +} + +void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userdata) +{ +	toggleMute(userdata, LLMute::flagTextChat); +} + +void LLParticipantList::LLParticipantListMenu::toggleMuteVoice(const LLSD& userdata) +{ +	toggleMute(userdata, LLMute::flagVoiceChat); +} + +void LLParticipantList::LLParticipantListMenu::moderateVoice(const LLSD& userdata) +{ + +} +void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(const LLSD& userdata) +{ +	LLSpeakerMgr::speaker_list_t speakers; +	mParent.mSpeakerMgr->getSpeakerList(&speakers, true); + +	const LLUUID& excluded_avatar_id = mUUIDs.front(); +	bool should_mute = userdata.asString() == "mute"; +	for (LLSpeakerMgr::speaker_list_t::iterator iter = speakers.begin(); +		iter != speakers.end(); ++iter) +	{ +		LLSpeaker* speakerp = (*iter).get(); +		LLUUID speaker_id = speakerp->mID; +		if (excluded_avatar_id == speaker_id) continue; + +		LLMute mute(speaker_id, speakerp->mDisplayName, speakerp->mType == LLSpeaker::SPEAKER_AGENT ? LLMute::AGENT : LLMute::OBJECT); + +		if (should_mute) +		{ +			LLMuteList::getInstance()->add(mute, LLMute::flagVoiceChat); +		} +		else +		{ +			LLMuteList::getInstance()->remove(mute, LLMute::flagVoiceChat); +		}  	} +  }  bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata) @@ -414,7 +490,7 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD&  		return mUUIDs.front() != gAgentID;  	}  	else -		if (item == "can_allow_text_chat") +		if (item == "can_allow_text_chat" || "can_moderate_voice" == item)  		{  			LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mParent.mSpeakerMgr->getSessionID());  			return im_session->mType == IM_SESSION_GROUP_START && mParent.mSpeakerMgr->findSpeaker(gAgentID)->mIsModerator; diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 86b38f5f1e..83191a5b8d 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -117,6 +117,7 @@ class LLParticipantList  		public:  			LLParticipantListMenu(LLParticipantList& parent):mParent(parent){};  			/*virtual*/ LLContextMenu* createMenu(); +			/*virtual*/ void show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y);  		protected:  			LLParticipantList& mParent;  		private: @@ -124,8 +125,13 @@ class LLParticipantList  			bool checkContextMenuItem(const LLSD& userdata);  			void toggleAllowTextChat(const LLSD& userdata); +			void toggleMute(const LLSD& userdata, U32 flags);  			void toggleMuteText(const LLSD& userdata); +			void toggleMuteVoice(const LLSD& userdata); +			// Voice moderation support +			void moderateVoice(const LLSD& userdata); +			void moderateVoiceOtherParticipants(const LLSD& userdata);  		};  	private: diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 0362fdbf56..8d80310769 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -54,6 +54,7 @@  #include "llscrolllistcell.h"  #include "llslider.h"  #include "lscript_rt_interface.h" +#include "lscript_library.h"  #include "lscript_export.h"  #include "lltextbox.h"  #include "lltooldraganddrop.h" diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 4f0c873c61..f66f725070 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -78,6 +78,22 @@ LLScreenChannelBase::~LLScreenChannelBase()  {  	mWorldViewRectConnection.disconnect();  } + +bool  LLScreenChannelBase::isHovering() +{ +	bool res = mHoveredToast != NULL; +	if (!res) +	{ +		return res; +	} + +	S32 x, y; +	mHoveredToast->screenPointToLocal(gViewerWindow->getCurrentMouseX(), +			gViewerWindow->getCurrentMouseY(), &x, &y); +	res = mHoveredToast->pointInView(x, y) == TRUE; +	return res; +} +  void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)  {  	S32 top_delta = old_world_rect.mTop - new_world_rect.mTop; @@ -125,6 +141,8 @@ LLScreenChannelBase(id)  void LLScreenChannel::init(S32 channel_left, S32 channel_right)  {  	LLScreenChannelBase::init(channel_left, channel_right); +	LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); +	updatePositionAndSize(world_rect, world_rect);  }  //-------------------------------------------------------------------------- @@ -136,7 +154,23 @@ LLScreenChannel::~LLScreenChannel()  //--------------------------------------------------------------------------  void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)  { -	LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect); +	S32 right_delta = old_world_rect.mRight - new_world_rect.mRight; +	LLRect this_rect = getRect(); + +	this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio()); +	switch(mChannelAlignment) +	{ +	case CA_LEFT : +		break; +	case CA_CENTRE : +		this_rect.setCenterAndSize(new_world_rect.getWidth() / 2, new_world_rect.getHeight() / 2, this_rect.getWidth(), this_rect.getHeight()); +		break; +	case CA_RIGHT : +		this_rect.mLeft -= right_delta; +		this_rect.mRight -= right_delta; +	} +	setRect(this_rect); +	redrawToasts();  }  //-------------------------------------------------------------------------- @@ -169,6 +203,7 @@ void LLScreenChannel::addToast(const LLToast::Params& p)  	if(show_toast)  	{  		mToastList.push_back(new_toast_elem); +		updateShowToastsState();  		redrawToasts();  	}	  	else // store_toast @@ -224,6 +259,7 @@ void LLScreenChannel::deleteToast(LLToast* toast)  	if(mHoveredToast == toast)  	{  		mHoveredToast  = NULL; +		startFadingToasts();  	}  	// close the toast @@ -405,26 +441,27 @@ void LLScreenChannel::showToastsBottom()  		{  			if( it != mToastList.rend()-1)  			{ -				stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastGap")) > getRect().mTop; +				S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap"); +				stop_showing_toasts = toast_top > getRect().mTop;  			}  		}  +		// at least one toast should be visible +		if(it == mToastList.rbegin()) +		{ +			stop_showing_toasts = false; +		} +  		if(stop_showing_toasts)  			break;  		if( !(*it).toast->getVisible() )  		{ -			if((*it).toast->isFirstLook()) -			{ -				(*it).toast->setVisible(TRUE); -			} -			else -			{ -				// HACK -				// EXT-2653: it is necessary to prevent overlapping for secondary showed toasts -				(*it).toast->setVisible(TRUE); -				gFloaterView->sendChildToBack((*it).toast); -			} +			// HACK +			// EXT-2653: it is necessary to prevent overlapping for secondary showed toasts +			(*it).toast->setVisible(TRUE); +			// Show toast behind floaters. (EXT-3089) +			gFloaterView->sendChildToBack((*it).toast);  		}		  	} @@ -566,6 +603,21 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer)  	mStartUpToastPanel->setVisible(TRUE);  } +// static -------------------------------------------------------------------------- +F32 LLScreenChannel::getHeightRatio() +{ +	F32 ratio = gSavedSettings.getF32("NotificationChannelHeightRatio"); +	if(0.0f > ratio) +	{ +		ratio = 0.0f; +	} +	else if(1.0f < ratio) +	{ +		ratio = 1.0f; +	} +	return ratio; +} +  //--------------------------------------------------------------------------  void LLScreenChannel::updateStartUpString(S32 num)  { @@ -608,7 +660,7 @@ void LLNotificationsUI::LLScreenChannel::startFadingToasts()  	if (!mToastList.size()) return;  	//because onMouseLeave is processed after onMouseEnter -	if (mHoveredToast) return; +	if (isHovering()) return;  	std::vector<ToastElem>::iterator it = mToastList.begin();  	while (it != mToastList.end()) @@ -685,39 +737,28 @@ void LLScreenChannel::removeToastsBySessionID(LLUUID id)  //--------------------------------------------------------------------------  void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)  { -	// because of LLViewerWindow::updateUI() that ALWAYS calls onMouseEnter BEFORE onMouseLeave -	// we must check this to prevent incorrect setting for hovering in a channel -	std::map<LLToast*, bool>::iterator it_first, it_second; -	S32 stack_size = mToastEventStack.size(); -	if(mouse_enter) -	{ -		mHoveredToast = toast; -	} -	else +	// because of LLViewerWindow::updateUI() that NOT ALWAYS calls onMouseEnter BEFORE onMouseLeave +	// we must check hovering directly to prevent incorrect setting for hovering in a channel +	S32 x,y; +	if (mouse_enter)  	{ -		mHoveredToast = NULL; -	} - -	switch(stack_size) -	{ -	case 0: -		mToastEventStack.insert(std::pair<LLToast*, bool>(toast, mouse_enter)); -		break; -	case 1: -		it_first = mToastEventStack.begin(); -		if((*it_first).second && !mouse_enter && ((*it_first).first != toast) ) +		toast->screenPointToLocal(gViewerWindow->getCurrentMouseX(), +				gViewerWindow->getCurrentMouseY(), &x, &y); +		bool hover = toast->pointInView(x, y) == TRUE; +		if (hover)  		{ -			mToastEventStack.clear();  			mHoveredToast = toast;  		} -		else +	} +	else if (mHoveredToast != NULL) +	{ +		mHoveredToast->screenPointToLocal(gViewerWindow->getCurrentMouseX(), +				gViewerWindow->getCurrentMouseY(), &x, &y); +		bool hover = mHoveredToast->pointInView(x, y) == TRUE; +		if (!hover)  		{ -			mToastEventStack.clear(); -			mToastEventStack.insert(std::pair<LLToast*, bool>(toast, mouse_enter)); +			mHoveredToast = NULL;  		} -		break; -	default: -		LL_ERRS ("LLScreenChannel::onToastHover: stack size error " ) << stack_size << llendl;  	}  	if(!isHovering()) @@ -727,7 +768,7 @@ void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)  //--------------------------------------------------------------------------  void LLScreenChannel::updateShowToastsState()  { -	LLFloater* floater = LLDockableFloater::getInstanceHandle().get(); +	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());  	if(!floater)  	{ @@ -735,27 +776,17 @@ void LLScreenChannel::updateShowToastsState()  		return;  	} -	// for IM floaters showed in a docked state - prohibit showing of ani toast -	if(dynamic_cast<LLIMFloater*>(floater) -		|| dynamic_cast<LLScriptFloater*>(floater) ) -	{ -		setShowToasts(!(floater->getVisible() && floater->isDocked())); -		if (!getShowToasts()) -		{ -			removeAndStoreAllStorableToasts(); -		} -	} -  	// *TODO: mantipov: what we have to do with derived classes: LLNotificationWellWindow & LLIMWelWindow?  	// See EXT-3081 for details  	// for Message Well floater showed in a docked state - adjust channel's height -	if(dynamic_cast<LLSysWellWindow*>(floater)) +	if(dynamic_cast<LLSysWellWindow*>(floater) || dynamic_cast<LLIMFloater*>(floater))  	{  		S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;  		LLRect this_rect = getRect();  		if(floater->getVisible() && floater->isDocked())  		{ -			channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastGap")); +			channel_bottom += floater->getRect().getHeight(); +			channel_bottom += floater->getDockControl()->getTongueHeight();  		}  		if(channel_bottom != this_rect.mBottom) diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 67f1c9bdc6..b8efbb148f 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -95,7 +95,7 @@ public:  	virtual void setControlHovering(bool control) { mControlHovering = control; } -	bool isHovering() { return mHoveredToast != NULL; } +	bool isHovering();  	void setCanStoreToasts(bool store) { mCanStoreToasts = store; } @@ -265,6 +265,11 @@ private:  	// create the StartUp Toast  	void	createStartUpToast(S32 notif_num, F32 timer); +	/** +	 * Notification channel and World View ratio(0.0 - always show 1 notification, 1.0 - max ratio). +	 */ +	static F32 getHeightRatio(); +  	// Channel's flags  	static bool	mWasStartUpToastShown; @@ -274,7 +279,6 @@ private:  	std::vector<ToastElem>		mToastList;  	std::vector<ToastElem>		mStoredToastList; -	std::map<LLToast*, bool>	mToastEventStack;  };  } diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 8de99a48aa..5c4f6e8860 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -39,6 +39,7 @@  #include "llfloaterreg.h"  #include "llnotifications.h"  #include "llscreenchannel.h" +#include "llsyswellwindow.h"  #include "lltoastnotifypanel.h"  #include "llviewerwindow.h"  #include "llimfloater.h" @@ -240,6 +241,14 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)  		LLBottomTray::getInstance()->getChicletPanel()->createChiclet<LLScriptChiclet>(object_id);  	} +	LLIMWellWindow::getInstance()->addObjectRow(object_id, set_new_message); + +	LLSD data; +	data["object_id"] = object_id; +	data["new_message"] = set_new_message; +	data["unread"] = 1; // each object has got only one floater +	mNewObjectSignal(data); +  	toggleScriptFloater(object_id, set_new_message);  } @@ -267,6 +276,8 @@ void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id)  	// remove related chiclet  	LLBottomTray::getInstance()->getChicletPanel()->removeChiclet(object_id); +	LLIMWellWindow::getInstance()->removeObjectRow(object_id); +  	// close floater  	LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", notification_id);  	if(floater) @@ -291,13 +302,6 @@ void LLScriptFloaterManager::removeNotificationByObjectId(const LLUUID& object_i  void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id, bool set_new_message)  { -	// hide "new message" icon from chiclet -	LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(object_id); -	if(chiclet) -	{ -		chiclet->setShowNewMessagesIcon(set_new_message); -	} -  	// kill toast  	using namespace LLNotificationsUI;  	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->findChannelByID( @@ -307,6 +311,11 @@ void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id, bool s  		channel->killToastByNotificationID(findNotificationToastId(object_id));  	} +	LLSD data; +	data["object_id"] = object_id; +	data["new_message"] = set_new_message; +	mToggleFloaterSignal(data); +  	// toggle floater  	LLScriptFloater::toggle(object_id);  } diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h index 8de7a28d0f..95ec5a4d9c 100644 --- a/indra/newview/llscriptfloater.h +++ b/indra/newview/llscriptfloater.h @@ -88,6 +88,11 @@ public:  	*/  	static void onToastButtonClick(const LLSD¬ification, const LLSD&response); +	typedef boost::signals2::signal<void(const LLSD&)> object_signal_t; + +	boost::signals2::connection addNewObjectCallback(const object_signal_t::slot_type& cb) { return mNewObjectSignal.connect(cb); } +	boost::signals2::connection addToggleObjectFloaterCallback(const object_signal_t::slot_type& cb) { return mToggleFloaterSignal.connect(cb); } +  private:  	struct LLNotificationData @@ -100,6 +105,9 @@ private:  	typedef std::map<LLUUID, LLNotificationData> script_notification_map_t;  	script_notification_map_t mNotifications; + +	object_signal_t mNewObjectSignal; +	object_signal_t mToggleFloaterSignal;  };  /** diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index bef7f5d6aa..1ebf624eeb 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -34,10 +34,12 @@  #include "llflatlistview.h"  #include "llfloaterreg.h" +#include "llnotifications.h"  #include "llsyswellwindow.h"  #include "llbottomtray.h" +#include "llscriptfloater.h"  #include "llviewercontrol.h"  #include "llviewerwindow.h" @@ -170,6 +172,7 @@ void LLSysWellWindow::setVisible(BOOL visible)  	if(mChannel)  	{  		mChannel->updateShowToastsState(); +		mChannel->redrawToasts();  	}  } @@ -188,6 +191,7 @@ void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock)  	if(mChannel)  	{  		mChannel->updateShowToastsState(); +		mChannel->redrawToasts();  	}  } @@ -356,7 +360,148 @@ BOOL LLIMWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask)  	return LLPanel::handleMouseDown(x, y, mask);  } +/************************************************************************/ +/*         ObjectRowPanel implementation                                */ +/************************************************************************/ + +LLIMWellWindow::ObjectRowPanel::ObjectRowPanel(const LLUUID& object_id, bool new_message/* = false*/) + : LLPanel() + , mChiclet(NULL) +{ +	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_active_object_row.xml", NULL); + +	initChiclet(object_id); + +	LLTextBox* obj_name = getChild<LLTextBox>("object_name"); +	obj_name->setValue(getObjectName(object_id)); + +	mCloseBtn = getChild<LLButton>("hide_btn"); +	mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::ObjectRowPanel::onClosePanel, this)); +} + +//--------------------------------------------------------------------------------- +LLIMWellWindow::ObjectRowPanel::~ObjectRowPanel() +{ +} + +std::string LLIMWellWindow::ObjectRowPanel::getObjectName(const LLUUID& object_id) +{ +	using namespace LLNotificationsUI; +	LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id); +	LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); +	if(!notification) +	{ +		llwarns << "Invalid notification" << llendl; +		return LLStringUtil::null; +	} + +	std::string text; + +	switch(getObjectType(notification)) +	{ +	case OBJ_SCRIPT: +		text = notification->getSubstitutions()["TITLE"].asString(); +		break; +	case OBJ_LOAD_URL: +		text = notification->getSubstitutions()["OBJECTNAME"].asString(); +		break; +	case OBJ_GIVE_INVENTORY: +		text = notification->getSubstitutions()["NAME"].asString(); +		break; +	default: +		text = getString("unknown_obj"); +		break; +	} + +	return text; +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onClosePanel() +{ +	LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(mChiclet->getSessionId()); +} + +//static +LLIMWellWindow::ObjectRowPanel::object_type_map LLIMWellWindow::ObjectRowPanel::initObjectTypeMap() +{ +	object_type_map type_map; +	type_map["ScriptDialog"] = OBJ_SCRIPT; +	type_map["LoadWebPage"] = OBJ_LOAD_URL; +	type_map["ObjectGiveItem"] = OBJ_GIVE_INVENTORY; +	return type_map; +} + +// static +LLIMWellWindow::ObjectRowPanel::EObjectType LLIMWellWindow::ObjectRowPanel::getObjectType(const LLNotificationPtr& notification) +{ +	if(!notification) +	{ +		llwarns << "Invalid notification" << llendl; +		return OBJ_UNKNOWN; +	} + +	static object_type_map type_map = initObjectTypeMap(); +	std::string name = notification->getName(); +	object_type_map::const_iterator it = type_map.find(name); +	if(it != type_map.end()) +	{ +		return it->second; +	} + +	llwarns << "Unknown object type" << llendl; +	return OBJ_UNKNOWN; +} + +void LLIMWellWindow::ObjectRowPanel::initChiclet(const LLUUID& object_id, bool new_message/* = false*/) +{ +	using namespace LLNotificationsUI; +	LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id); +	LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); +	if(!notification) +	{ +		llwarns << "Invalid notification" << llendl; +		return; +	} + +	// Choose which of the pre-created chiclets to use. +	switch(getObjectType(notification)) +	{ +	case OBJ_GIVE_INVENTORY: +		mChiclet = getChild<LLInvOfferChiclet>("inv_offer_chiclet"); +		break; +	default: +		mChiclet = getChild<LLScriptChiclet>("object_chiclet"); +		break; +	} + +	mChiclet->setVisible(true); +	mChiclet->setSessionId(object_id); +//	mChiclet->setShowNewMessagesIcon(new_message); +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onMouseEnter(S32 x, S32 y, MASK mask) +{ +	setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected")); +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onMouseLeave(S32 x, S32 y, MASK mask) +{ +	setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected")); +} + +//--------------------------------------------------------------------------------- +// virtual +BOOL LLIMWellWindow::ObjectRowPanel::handleMouseDown(S32 x, S32 y, MASK mask) +{ +	// Pass the mouse down event to the chiclet (EXT-596). +	if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown() +		mChiclet->onMouseDown(); +	return LLPanel::handleMouseDown(x, y, mask); +}  /************************************************************************/  /*         LLNotificationWellWindow implementation                      */ @@ -503,6 +648,7 @@ LLIMWellWindow::LLIMWellWindow(const LLSD& key)  {  	LLIMMgr::getInstance()->addSessionObserver(this);  	LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findIMChiclet, this, _1)); +	LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findObjectChiclet, this, _1));  }  LLIMWellWindow::~LLIMWellWindow() @@ -557,6 +703,18 @@ void LLIMWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID  	}  } +LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& object_id) +{ +	LLChiclet* res = NULL; +	ObjectRowPanel* panel = mMessageList->getTypedItemByValue<ObjectRowPanel>(object_id); +	if (panel != NULL) +	{ +		res = panel->mChiclet; +	} + +	return res; +} +  //////////////////////////////////////////////////////////////////////////  // PRIVATE METHODS  LLChiclet* LLIMWellWindow::findIMChiclet(const LLUUID& sessionId) @@ -615,4 +773,41 @@ void LLIMWellWindow::delIMRow(const LLUUID& sessionId)  	}  } +void LLIMWellWindow::addObjectRow(const LLUUID& object_id, bool new_message/* = false*/) +{ +	if (mMessageList->getItemByValue(object_id) == NULL) +	{ +		ObjectRowPanel* item = new ObjectRowPanel(object_id, new_message); +		if (mMessageList->insertItemAfter(mSeparator, item, object_id)) +		{ +			handleItemAdded(IT_INSTANT_MESSAGE); +		} +		else +		{ +			llwarns << "Unable to add Object Row into the list, objectID: " << object_id << llendl; +			item->die(); +		} +		reshapeWindow(); +	} +} + +void LLIMWellWindow::removeObjectRow(const LLUUID& object_id) +{ +	if (mMessageList->removeItemByValue(object_id)) +	{ +		handleItemRemoved(IT_INSTANT_MESSAGE); +	} +	else +	{ +		llwarns << "Unable to remove Object Row from the list, objectID: " << object_id << llendl; +	} + +	reshapeWindow(); +	// hide chiclet window if there are no items left +	if(isWindowEmpty()) +	{ +		setVisible(FALSE); +	} +} +  // EOF diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index adbc83677d..43b2723df0 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -46,7 +46,7 @@  class LLFlatListView;  class LLChiclet;  class LLIMChiclet; - +class LLScriptChiclet;  class LLSysWellWindow : public LLDockableFloater @@ -126,14 +126,12 @@ protected:   *    * It contains a list of notifications that have not been responded to.   */ -class LLNotificationWellWindow : public LLSysWellWindow, public LLInitClass<LLNotificationWellWindow> +class LLNotificationWellWindow : public LLSysWellWindow  {  public:  	LLNotificationWellWindow(const LLSD& key);  	static LLNotificationWellWindow* getInstance(const LLSD& key = LLSD()); -	static void initClass() { getInstance(); } -  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setVisible(BOOL visible); @@ -181,11 +179,16 @@ public:  	/*virtual*/ void sessionRemoved(const LLUUID& session_id);  	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); +	void addObjectRow(const LLUUID& object_id, bool new_message = false); +	void removeObjectRow(const LLUUID& object_id); +  protected:  	/*virtual*/ const std::string& getAnchorViewName() { return IM_WELL_ANCHOR_NAME; }  private:  	LLChiclet * findIMChiclet(const LLUUID& sessionId); +	LLChiclet* findObjectChiclet(const LLUUID& object_id); +  	void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId);  	void delIMRow(const LLUUID& sessionId); @@ -210,6 +213,37 @@ private:  		LLButton*	mCloseBtn;  		const LLSysWellWindow* mParent;  	}; + +	class ObjectRowPanel: public LLPanel +	{ +		typedef enum e_object_type +		{ +			OBJ_UNKNOWN, + +			OBJ_SCRIPT, +			OBJ_GIVE_INVENTORY, +			OBJ_LOAD_URL +		}EObjectType; + +	public: +		ObjectRowPanel(const LLUUID& object_id, bool new_message = false); +		virtual ~ObjectRowPanel(); +		/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); +		/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); +		/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); +	private: +		void onClosePanel(); +		static EObjectType getObjectType(const LLNotificationPtr& notification); +		void initChiclet(const LLUUID& object_id, bool new_message = false); +		std::string getObjectName(const LLUUID& object_id); + +		typedef std::map<std::string, EObjectType> object_type_map; +		static object_type_map initObjectTypeMap(); +	public: +		LLIMChiclet* mChiclet; +	private: +		LLButton*	mCloseBtn; +	};  };  #endif // LL_LLSYSWELLWINDOW_H diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index fc7c029a17..4131e2755a 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -67,7 +67,8 @@ LLToast::LLToast(const LLToast::Params& p)  	mHideBtn(NULL),  	mNotification(p.notification),  	mIsHidden(false), -	mHideBtnPressed(false) +	mHideBtnPressed(false), +	mIsTip(p.is_tip)  {  	LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL); @@ -98,10 +99,30 @@ BOOL LLToast::postBuild()  		mTimer.stop();  	} +	if (mIsTip) +	{ +		mTextEditor = mPanel->getChild<LLTextEditor>("text_editor_box"); + +		if (mTextEditor) +		{ +			mTextEditor->setMouseUpCallback(boost::bind(&LLToast::hide,this)); +			mPanel->setMouseUpCallback(boost::bind(&LLToast::handleTipToastClick, this, _2, _3, _4)); +		} +	} +  	return TRUE;  }  //-------------------------------------------------------------------------- +void LLToast::handleTipToastClick(S32 x, S32 y, MASK mask) +{ +	if (!mTextEditor->getRect().pointInRect(x, y)) +	{ +		hide(); +	} +} + +//--------------------------------------------------------------------------  void LLToast::setHideButtonEnabled(bool enabled)  {  	if(mHideBtn) diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index d08e46e160..0c3c598704 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -40,6 +40,7 @@  #include "llnotificationptr.h"  #include "llviewercontrol.h" +#include "lltexteditor.h"  #define MOUSE_LEAVE false  #define MOUSE_ENTER true @@ -155,6 +156,8 @@ public:  private: +	void handleTipToastClick(S32 x, S32 y, MASK mask); +  	// check timer  	bool	lifetimeHasExpired();  	// on timer finished function @@ -169,8 +172,9 @@ private:  	F32			mToastLifetime; // in seconds  	F32			mToastFadingTime; // in seconds -	LLPanel*	mPanel; -	LLButton*	mHideBtn; +	LLPanel*		mPanel; +	LLButton*		mHideBtn; +	LLTextEditor*	mTextEditor;  	LLColor4	mBgColor;  	bool		mCanFade; @@ -178,6 +182,7 @@ private:  	bool		mHideBtnEnabled;  	bool		mHideBtnPressed;  	bool		mIsHidden;  // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849) +	bool		mIsTip;  };  } diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index 7beba59c83..ed9e2e8818 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -85,7 +85,6 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  		sys_msg_icon->setVisible(FALSE);  		mAvatar->setValue(p.avatar_id); -		setMouseDownCallback(boost::bind(&LLToastIMPanel::onClickToastIM, this));  	}  	S32 maxLinesCount; @@ -102,11 +101,13 @@ LLToastIMPanel::~LLToastIMPanel()  {  } -//-------------------------------------------------------------------------- -void LLToastIMPanel::onClickToastIM() +//virtual +BOOL LLToastIMPanel::handleMouseDown(S32 x, S32 y, MASK mask)  { -	mNotification->respond(mNotification->getResponseTemplate()); -} - -//-------------------------------------------------------------------------- +	if (LLPanel::handleMouseDown(x,y,mask) == FALSE) +	{ +		mNotification->respond(mNotification->getResponseTemplate()); +	} +	return TRUE; +} diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index 23f08ef610..53661f2cf6 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -57,12 +57,10 @@ public:  	LLToastIMPanel(LLToastIMPanel::Params &p);  	virtual ~LLToastIMPanel(); - +	/*virtual*/ BOOL 	handleMouseDown(S32 x, S32 y, MASK mask);  private:  	static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT; -	void onClickToastIM(); -  	LLNotificationPtr	mNotification;  	LLUUID				mSessionID;  	LLAvatarIconCtrl*	mAvatar; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 2d0a14dc70..aa35f22930 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -772,6 +772,9 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  		{  			LLInventoryObject* cargo = locateInventory(item, cat); +			// fix for EXT-3191 +			if (NULL == cargo) return; +  			EAcceptance item_acceptance = ACCEPT_NO;  			handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE,  												mCargoTypes[mCurItemIndex], diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8c0529e344..31bd264e3a 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2096,8 +2096,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			LLSD payload;  			payload["object_id"] = session_id;  			payload["owner_id"] = from_id; +			payload["from_id"] = from_id;  			payload["slurl"] = location;  			payload["name"] = name; +			std::string session_name; +			gCacheName->getFullName(from_id, session_name); +			payload["SESSION_NAME"] = session_name;  			if (from_group)  			{  				payload["groupowned"] = "true"; diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 2fae78cdfb..7a1abfd4e8 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -2525,7 +2525,8 @@ boost::signals2::connection LLViewerParcelMgr::setTeleportFailedCallback(parcel_   */  void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos)  { -	if (local) +	// Treat only teleports within the same parcel as local (EXT-3139). +	if (local && LLViewerParcelMgr::getInstance()->inAgentParcel(new_pos))  	{  		// Local teleport. We already have the agent parcel data.  		// Emit the signal immediately. @@ -2533,7 +2534,7 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos  	}  	else  	{ -		// Non-local teleport. +		// Non-local teleport (inter-region or between different parcels of the same region).  		// The agent parcel data has not been updated yet.  		// Let's wait for the update and then emit the signal.  		mTeleportInProgress = TRUE; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 7e1e7c940f..63acba50e7 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -4279,6 +4279,7 @@ void LLVoiceClient::mediaStreamUpdatedEvent(  				{  					// Send the voice chat invite to the GUI layer  					// *TODO: Question: Should we correlate with the mute list here? +					session->mIncoming = true;  					session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);  					session->mVoiceInvitePending = true;  					if(session->mName.empty()) @@ -6353,6 +6354,20 @@ LLVoiceClient::sessionState *LLVoiceClient::findSession(const LLUUID &participan  	return result;  } +bool LLVoiceClient::isSessionIncoming(const LLUUID &session_id) +{ +	for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++) +	{ +		sessionState *session = *iter; +		if(session->mIMSessionID == session_id) +		{ +			return session->mIncoming; +			break; +		} +	} +	return false; +} +  LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, const std::string &handle)  {  	sessionState *result = NULL; diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 347fae6156..edfe0173f8 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -527,6 +527,8 @@ static	void updatePosition(void);  		// Currently this will be false only for PSTN P2P calls.  		// NOTE: this will return true if the session can't be found.   		bool isSessionTextIMPossible(const LLUUID &session_id); + +		bool isSessionIncoming(const LLUUID &session_id);  	private: diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png Binary files differnew file mode 100644 index 0000000000..60676b43fd --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png Binary files differnew file mode 100644 index 0000000000..98cde96aff --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 607df10048..24d3512bcb 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -375,7 +375,7 @@ with the same filename but different name   <texture name="Parcel_PushNo_Light" file_name="icons/Parcel_PushNo_Light.png" preload="false" />   <texture name="Parcel_R_Light" file_name="icons/Parcel_R_Light.png" preload="false" />   <texture name="Parcel_Scripts_Light" file_name="icons/Parcel_Scripts_Light.png" preload="false" /> - <texture name="Parcel_ScriptsNo_Light" file_name="icons/Parcel_ScriptsNo_Light.png" preload="false" /> + <texture name="Parcel_ScriptsNo_Light" file_name="icons/Parcel_ScriptsNo_Dark.png" preload="false" />   <texture name="Parcel_Voice_Light" file_name="icons/Parcel_Voice_Light.png" preload="false" />   <texture name="Parcel_VoiceNo_Light" file_name="icons/Parcel_VoiceNo_Light.png" preload="false" /> @@ -592,6 +592,9 @@ with the same filename but different name    <texture name="Unread_IM" file_name="bottomtray/Unread_IM.png" preload="false" />    <texture name="Unread_Msg" file_name="bottomtray/Unread_Msg.png" preload="false" /> +   +  <texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png" /> +  <texture name="WellButton_Lit_Selected" file_name="bottomtray/WellButton_Lit_Selected.png" />    <texture name="VoicePTT_Lvl1" file_name="bottomtray/VoicePTT_Lvl1.png" preload="false" />    <texture name="VoicePTT_Lvl2" file_name="bottomtray/VoicePTT_Lvl2.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml index 526fda90d1..acd59b6f09 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -36,21 +36,25 @@       top="35"       width="36" />      <text +     clip_partial="true"       font="SansSerifLarge" -     height="20" +     height="37"       layout="topleft"       left="77"       name="caller name" -     top="27" +     top="20" +     use_ellipses="true"       width="315"       word_wrap="true" />      <text +     clip_partial="true"       font="SansSerif" -     height="50" +     height="30"       layout="topleft"       left="77"       name="question" -     top="52" +     top_pad="5" +     use_ellipses="true"       width="315"       word_wrap="true">       Do you want to leave [CURRENT_CHAT] and join this voice chat? diff --git a/indra/newview/skins/default/xui/en/menu_participant_list.xml b/indra/newview/skins/default/xui/en/menu_participant_list.xml index 5ab327a182..0422972cd4 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml @@ -89,4 +89,51 @@           function="ParticipantList.EnableItem"           parameter="can_allow_text_chat" />      </menu_item_check> +    <menu_item_separator +     layout="topleft" +     name="moderate_voice_separator" /> +    <menu_item_call +     label="Mute this participant" +     layout="topleft" +     name="ModerateVoiceMuteSelected"> +        <on_click +         function="ParticipantList.ModerateVoice" +         parameter="selected" /> +        <on_enable +         function="ParticipantList.EnableItem" +         parameter="can_moderate_voice" /> +    </menu_item_call> +    <menu_item_call +     label="Mute everyone else" +     layout="topleft" +     name="ModerateVoiceMuteOthers"> +        <on_click +         function="ParticipantList.ModerateVoice" +         parameter="others" /> +        <on_enable +         function="ParticipantList.EnableItem" +         parameter="can_moderate_voice" /> +    </menu_item_call> +    <menu_item_call +     label="Unmute this participant" +     layout="topleft" +     name="ModerateVoiceUnMuteSelected"> +        <on_click +         function="ParticipantList.ModerateVoice" +         parameter="selected" /> +        <on_enable +         function="ParticipantList.EnableItem" +         parameter="can_moderate_voice" /> +    </menu_item_call> +    <menu_item_call +     label="Unmute everyone else" +     layout="topleft" +     name="ModerateVoiceUnMuteOthers"> +        <on_click +         function="ParticipantList.ModerateVoice" +         parameter="others" /> +        <on_enable +         function="ParticipantList.EnableItem" +         parameter="can_moderate_voice" /> +    </menu_item_call>  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index c3a2540b2e..39469f7101 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -34,7 +34,6 @@           function="Avatar.Call" />      </menu_item_call>      <menu_item_call -     enabled="false"       label="Share"       layout="topleft"       name="Share"> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 416b1b6973..22896d59c3 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4719,10 +4719,6 @@ The objects on the selected parcel that are NOT owned by you have been returned     type="notify">  Message from [NAME]:  [MSG] -    <usetemplate -     name="okcancelbuttons" -     notext="OK" -     yestext="Inspect"/>    </notification>    <notification diff --git a/indra/newview/skins/default/xui/en/panel_active_object_row.xml b/indra/newview/skins/default/xui/en/panel_active_object_row.xml new file mode 100644 index 0000000000..7657fb8055 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_active_object_row.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel +  name="panel_activeim_row" +  layout="topleft" +  follows="left|right" +  top="0" +  left="0" +  height="35" +  width="318" +  background_opaque="false" +  background_visible="true" +  bg_alpha_color="0.0 0.0 0.0 0.0" > +  <string +   name="unknown_obj"> +    Unknown Object +  </string> +  <chiclet_script +    name="object_chiclet" +    layout="topleft" +    follows="left" +    top="3" +    left="5" +    height="25" +    width="25" +    visible="false" +    speaker.name="speaker_p2p" +    speaker.width="20" +    speaker.height="25" +    speaker.left="25" +    speaker.top="25" +    speaker.auto_update="true" +    speaker.draw_border="false" +    speaker.visible="false"> +  </chiclet_script> +  <chiclet_offer +    name="inv_offer_chiclet" +    layout="topleft" +    follows="left" +    top="3" +    left="5" +    height="25" +    width="25" +    visible="false" +    speaker.name="speaker_p2p" +    speaker.width="20" +    speaker.height="25" +    speaker.left="25" +    speaker.top="25" +    speaker.auto_update="true" +    speaker.draw_border="false" +    speaker.visible="false"> +  </chiclet_offer> +	<text +    type="string" +    name="object_name" +    layout="topleft" +    top="10" +    left_pad="20" +    height="14" +    width="245" +    length="1" +    follows="right|left" +    use_ellipses="true" +    font="SansSerifBold"> +    Unnamed Object +  </text> +  <button +    top="10" +    right="-5" +    width="17" +    height="17" +    layout="topleft" +    follows="right" +    name="hide_btn" +    mouse_opaque="true" +    label="" +    tab_stop="false" +    image_unselected="Toast_CloseBtn" +    image_selected="Toast_CloseBtn" +  /> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 7f847237ce..a41d492624 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -324,6 +324,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.           min_width="34"           user_resize="false">              <chiclet_im_well +             flash_period="0.3"                follows="right"               height="23"               layout="topleft" @@ -331,6 +332,14 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.               name="im_well"               top="4"               width="34"> +             <!-- +Emulate 4 states of button by background images, see detains in EXT-3147. The same should be for notification_well button +xml attribute           Description +image_unselected        "Unlit" - there are no new messages +image_selected          "Unlit" + "Selected" - there are no new messages and the Well is open +image_pressed           "Lit" - there are new messages +image_pressed_selected  "Lit" + "Selected" - there are new messages and the Well is open +             -->                  <button                   auto_resize="true"                   flash_color="EmphasisColor" @@ -339,10 +348,11 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.                   height="23"                   image_overlay="Notices_Unread"                   image_overlay_alignment="center"  -                 image_pressed="PushButton_Press" -                 image_pressed_selected="PushButton_Selected_Press" +                 image_pressed="WellButton_Lit" +                 image_pressed_selected="WellButton_Lit_Selected"                   image_selected="PushButton_Selected_Press"                   left="0" +                 max_displayed_count="99"                   name="Unread IM messages"                   pad_left="0"                   pad_right="0" @@ -365,17 +375,19 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.           min_width="34"           user_resize="false">              <chiclet_notification +             flash_period="0.25"               follows="right"               height="23"               layout="topleft"               left="0" +             max_displayed_count="99"               name="notification_well"               top="4"               width="34">                <button                   image_selected="PushButton_Selected_Press" -                 image_pressed="PushButton_Press" -		 image_pressed_selected="PushButton_Selected_Press" +                 image_pressed="WellButton_Lit" +                 image_pressed_selected="WellButton_Lit_Selected"                auto_resize="true"                 halign="center"                 height="23" diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index e5dc4df0f8..af73faf9a1 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -23,7 +23,7 @@ Hover your mouse over the options for more help.      </panel.string>      <text_editor       type="string" -     follows="left|top" +     follows="left|top|right"       left="5"       height="60"       layout="topleft" @@ -37,7 +37,7 @@ Hover your mouse over the options for more help.      <name_list       column_padding="0"       draw_heading="true" -     follows="left|top" +     follows="left|top|right"       heading_height="20"       height="156"       layout="topleft" @@ -55,10 +55,10 @@ Hover your mouse over the options for more help.           relative_width="0.4" />        </name_list>           <text -         follows="left|top" +         follows="left|top|right"           type="string"           height="12" -         layout="topleft" +         layout="left|top|right"           left="5"           name="active_title_label"           top_pad="5" @@ -66,7 +66,7 @@ Hover your mouse over the options for more help.              My Title          </text>          <combo_box -         follows="left|top" +         follows="left|top|right"           height="20"           layout="topleft"           left="5" @@ -98,7 +98,7 @@ Hover your mouse over the options for more help.           bevel_style="in"           border="true"           bg_alpha_color="FloaterUnfocusBorderColor" -         follows="left|top" +         follows="left|top|right"           height="88"           layout="topleft"           left="2" @@ -106,7 +106,7 @@ Hover your mouse over the options for more help.           name="preferences_container"           top_pad="2">          <check_box -         follows="right|top" +         follows="right|top|left"           height="16"           label="Open enrollment"           layout="topleft" @@ -126,21 +126,21 @@ Hover your mouse over the options for more help.           width="300" />          <spinner           decimal_digits="0" -         follows="left|top" +         follows="left|top|right"           halign="left"           height="16"           increment="1"           label_width="15"           label="L$"           layout="topleft" -         right="-10" +         right="-30"           max_val="99999"           left_pad="0"           name="spin_enrollment_fee"           tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked." -         width="100" /> +         width="80" />           <combo_box -         follows="left|top" +         follows="left|top|right"           height="20"           layout="topleft"           left="10" @@ -158,7 +158,7 @@ Hover your mouse over the options for more help.               value="Mature" />          </combo_box>          <check_box -         follows="left|top" +         follows="left|top|right"           height="16"           initial_value="true"           label="Show in search" diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml index c02dabed2c..9e7c9477d4 100644 --- a/indra/newview/skins/default/xui/en/panel_notes.xml +++ b/indra/newview/skins/default/xui/en/panel_notes.xml @@ -120,6 +120,7 @@           left="0"           mouse_opaque="false"           name="add_friend" +         tool_tip="Offer friendship to the resident"           top="5"           width="55" />          <button @@ -128,6 +129,7 @@           label="IM"           layout="topleft"           name="im" +         tool_tip="Open instant message session"           top="5"           left_pad="5"           width="40" /> @@ -137,6 +139,7 @@           label="Call"           layout="topleft"           name="call" +         tool_tip="Call this resident"           left_pad="5"           top="5"           width="55" /> @@ -147,6 +150,7 @@           label="Map"           layout="topleft"           name="show_on_map_btn" +         tool_tip="Show the resident on the map"           top="5"           left_pad="5"           width="50" /> @@ -156,6 +160,7 @@           label="Teleport"           layout="topleft"           name="teleport" +         tool_tip="Offer teleport"           left_pad="5"           top="5"           width="90" /> diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 6be203ef9c..638bc3cabd 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -286,6 +286,7 @@           left="0"           mouse_opaque="false"           name="add_friend" +         tool_tip="Offer friendship to the resident"           top="5"           width="77" />          <button @@ -294,6 +295,7 @@           label="IM"           layout="topleft"           name="im" +         tool_tip="Open instant message session"           top="5"           left_pad="5"           width="33" /> @@ -303,6 +305,7 @@           label="Call"           layout="topleft"           name="call" +         tool_tip="Call this resident"           left_pad="5"           top="5"           width="40" /> @@ -313,6 +316,7 @@           label="Map"           layout="topleft"           name="show_on_map_btn" +         tool_tip="Show the resident on the map"           top="5"           left_pad="5"           width="44" /> @@ -322,6 +326,7 @@           label="Teleport"           layout="topleft"           name="teleport" +         tool_tip="Offer teleport"           left_pad="5"           top="5"           width="67" /> @@ -331,6 +336,7 @@           label="▼"           layout="topleft"           name="overflow_btn" +         tool_tip="Pay money to or share inventory with the resident"           right="-1"           top="5"           width="21" /> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index d5022de089..c3650c71c3 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2856,6 +2856,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE].    <string name="inventory_item_offered-im">      Inventory item offered    </string> +  <string name="share_alert"> +    Drag items from inventory here +  </string> +    <string name="only_user_message">      You are the only user in this session.  | 
