diff options
104 files changed, 1061 insertions, 388 deletions
| diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 74b49b846e..82ec02d2eb 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -26,7 +26,6 @@ include_directories(      )  set(llui_SOURCE_FILES -    llalertdialog.cpp      llbutton.cpp      llcheckboxctrl.cpp      llclipboard.cpp @@ -112,7 +111,6 @@ set(llui_SOURCE_FILES  set(llui_HEADER_FILES      CMakeLists.txt -    llalertdialog.h      llbutton.h      llcallbackmap.h      llcheckboxctrl.h diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 9c69e4f2b6..9dc7861992 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -38,6 +38,8 @@  //static  LLHandle<LLFloater> LLDockableFloater::sInstanceHandle; +static const std::string VOICE_FLOATER("floater_voice_controls"), IM_FLOATER("panel_im"); +  //static  void LLDockableFloater::init(LLDockableFloater* thiz)  { @@ -98,8 +100,15 @@ void LLDockableFloater::toggleInstance(const LLSD& sdname)  	else if (instance != NULL)  	{  		instance->setMinimized(FALSE); -		instance->setVisible(TRUE); -		gFloaterView->bringToFront(instance); +		if (instance->getVisible()) +		{ +			instance->setVisible(FALSE); +		} +		else +		{ +			instance->setVisible(TRUE); +			gFloaterView->bringToFront(instance); +		}  	}  } @@ -107,9 +116,11 @@ void LLDockableFloater::resetInstance()  {  	if (mUniqueDocking && sInstanceHandle.get() != this)  	{ -		if (sInstanceHandle.get() != NULL && sInstanceHandle.get()->isDocked()) +		if (sInstanceHandle.get() != NULL && sInstanceHandle.get()->isDocked() +				&& (getName() != VOICE_FLOATER || sInstanceHandle.get()->getName() != IM_FLOATER) +					&& (getName() !=  IM_FLOATER || sInstanceHandle.get()->getName() != VOICE_FLOATER))  		{ -			sInstanceHandle.get()->setVisible(FALSE); +				sInstanceHandle.get()->setVisible(FALSE);  		}  		sInstanceHandle = getHandle();  	} diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 750b190953..de2b43bf13 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -37,7 +37,6 @@  #define LLPANEL_CPP  #include "llpanel.h" -#include "llalertdialog.h"  #include "llfocusmgr.h"  #include "llfontgl.h"  #include "llrect.h" diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 72630cc413..492d70a956 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -228,7 +228,6 @@ set(viewer_SOURCE_FILES      llgroupactions.cpp      llgrouplist.cpp      llgroupmgr.cpp -    llgroupnotify.cpp      llhomelocationresponder.cpp      llhudeffect.cpp      llhudeffectbeam.cpp @@ -299,7 +298,6 @@ set(viewer_SOURCE_FILES      llnotificationofferhandler.cpp      llnotificationscripthandler.cpp      llnotificationtiphandler.cpp -    llnotify.cpp      lloutputmonitorctrl.cpp      lloverlaybar.cpp      llpanelavatar.cpp @@ -738,7 +736,6 @@ set(viewer_HEADER_FILES      llgroupactions.h      llgrouplist.h      llgroupmgr.h -    llgroupnotify.h      llhomelocationresponder.h      llhudeffect.h      llhudeffectbeam.h @@ -804,7 +801,6 @@ set(viewer_HEADER_FILES      llnetmap.h      llnotificationhandler.h      llnotificationmanager.h -    llnotify.h      lloutputmonitorctrl.h      lloverlaybar.h      llpanelavatar.h diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 3114a37ada..1e2eac39eb 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -41,7 +41,6 @@  #include "llinventoryobserver.h"  #include "llinventorypanel.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llviewerregion.h"  #include "llvoavatarself.h"  #include "llwearable.h" diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1ccb691fb3..07b3399637 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -39,7 +39,6 @@  #include "llfeaturemanager.h"  #include "lluictrlfactory.h"  #include "lltexteditor.h" -#include "llalertdialog.h"  #include "llerrorcontrol.h"  #include "llviewertexturelist.h"  #include "llgroupmgr.h" @@ -112,7 +111,6 @@  #include "apr_dso.h"  #include <boost/lexical_cast.hpp> -#include "llnotify.h"  #include "llviewerkeyboard.h"  #include "lllfsthread.h"  #include "llworkerthread.h" diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 1d03cc8823..a2322e28b4 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -39,7 +39,6 @@  #include "llcompilequeue.h"  #include "llfloaterbuycurrency.h"  #include "llfilepicker.h" -#include "llnotify.h"  #include "llinventoryobserver.h"  #include "llinventorypanel.h"  #include "llpermissionsflags.h" diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 5f90a7627f..33dc7ee2c8 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -61,6 +61,7 @@  #include "llviewerregion.h"  #include "llimfloater.h"  #include "lltrans.h" +#include "llcallingcard.h"  // static  void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name) @@ -265,6 +266,24 @@ bool LLAvatarActions::isCalling(const LLUUID &id)  	return (LLIMModel::getInstance()->findIMSession(session_id) != NULL);  } +//static +bool LLAvatarActions::canCall(const LLUUID &id) +{ +	if(isFriend(id)) +	{ +		return LLAvatarTracker::instance().isBuddyOnline(id) && LLVoiceClient::voiceEnabled(); +	} +	else +	{ +		// don't need to check online/offline status because "usual resident" (resident that is not a friend) +		// can be only ONLINE. There is no way to see "usual resident" in OFFLINE status. If we see "usual +		// resident" it automatically means that the resident is ONLINE. So to make a call to the "usual resident" +		// we need to check only that "our" voice is enabled. +		return LLVoiceClient::voiceEnabled(); +	} + +} +  // static  void LLAvatarActions::startConference(const std::vector<LLUUID>& ids)  { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 2dd2a4c4b1..01c18d4228 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -129,6 +129,11 @@ public:  	static bool isCalling(const LLUUID &id);  	/** +	 * @return true if call to the resident can be made (resident is online and voice is enabled) +	 */ + +	static bool canCall(const LLUUID &id); +	/**  	 * Invite avatar to a group.  	 */	  	static void inviteToGroup(const LLUUID& id); diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 895b4ed80e..2f5523e04d 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -33,8 +33,12 @@  #include "llviewerprecompiledheaders.h" +#include "llnotificationsutil.h" +#include "lltrans.h" +  #include "llcallfloater.h" +#include "llagent.h"  #include "llagentdata.h" // for gAgentID  #include "llavatarlist.h"  #include "llbottomtray.h" @@ -79,8 +83,12 @@ LLCallFloater::LLCallFloater(const LLSD& key)  , mAvatarList(NULL)  , mNonAvatarCaller(NULL)  , mVoiceType(VC_LOCAL_CHAT) +, mAgentPanel(NULL) +, mSpeakingIndicator(NULL) +, mIsModeratorMutedVoice(false)  {  	mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL); +	LLVoiceClient::getInstance()->addObserver(this);  }  LLCallFloater::~LLCallFloater() @@ -88,6 +96,13 @@ LLCallFloater::~LLCallFloater()  	mChannelChangedConnection.disconnect();  	delete mPaticipants;  	mPaticipants = NULL; + +	// Don't use LLVoiceClient::getInstance() here  +	// singleton MAY have already been destroyed. +	if(gVoiceClient) +	{ +		gVoiceClient->removeObserver(this); +	}  }  // virtual @@ -120,6 +135,34 @@ void LLCallFloater::onOpen(const LLSD& /*key*/)  {  } +// virtual +void LLCallFloater::draw() +{ +	// we have to refresh participants to display ones not in voice as disabled. +	// It should be done only when she joins or leaves voice chat. +	// But seems that LLVoiceClientParticipantObserver is not enough to satisfy this requirement. +	// *TODO: mantipov: remove from draw() +	onChange(); + +	bool is_moderator_muted = gVoiceClient->getIsModeratorMuted(gAgentID); + +	if (mIsModeratorMutedVoice != is_moderator_muted) +	{ +		setModeratorMutedVoice(is_moderator_muted); +	} + +	LLDockableFloater::draw(); +} + +// virtual +void LLCallFloater::onChange() +{ +	if (NULL == mPaticipants) return; + +	mPaticipants->refreshVoiceState(); +} + +  //////////////////////////////////////////////////////////////////////////  /// PRIVATE SECTION  ////////////////////////////////////////////////////////////////////////// @@ -165,9 +208,19 @@ void LLCallFloater::updateSession()  			mVoiceType = VC_PEER_TO_PEER;  			break;  		case IM_SESSION_CONFERENCE_START: -			mVoiceType = VC_AD_HOC_CHAT; +		case IM_SESSION_GROUP_START: +		case IM_SESSION_INVITE: +			if (gAgent.isInGroup(session_id)) +			{ +				mVoiceType = VC_GROUP_CHAT; +			} +			else +			{ +				mVoiceType = VC_AD_HOC_CHAT;				 +			}  			break;  		default: +			llwarning("Failed to determine voice call IM type", 0);  			mVoiceType = VC_GROUP_CHAT;  			break;  		} @@ -188,6 +241,7 @@ void LLCallFloater::updateSession()  	childSetVisible("leave_btn_panel", !is_local_chat);  	refreshPartisipantList(); +	updateModeratorState();  }  void LLCallFloater::refreshPartisipantList() @@ -220,11 +274,20 @@ void LLCallFloater::refreshPartisipantList()  		{  			mAvatarList->setNoItemsCommentText(getString("no_one_near"));  		} +		mPaticipants->refreshVoiceState();	  	}  }  void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/)  { +	// Don't update participant list if no channel info is available. +	// Fix for ticket EXT-3427 +	// @see LLParticipantList::~LLParticipantList() +	if(LLVoiceChannel::getCurrentVoiceChannel() &&  +		LLVoiceChannel::STATE_NO_CHANNEL_INFO == LLVoiceChannel::getCurrentVoiceChannel()->getState()) +	{ +		return; +	}  	// Forget speaker manager from the previous session to avoid using it after session was destroyed.  	mSpeakerManager = NULL;  	updateSession(); @@ -263,13 +326,52 @@ void LLCallFloater::updateTitle()  void LLCallFloater::initAgentData()  { -	childSetValue("user_icon", gAgentID); +	mAgentPanel = getChild<LLPanel> ("my_panel"); + +	if ( mAgentPanel ) +	{ +		mAgentPanel->childSetValue("user_icon", gAgentID); + +		std::string name; +		gCacheName->getFullName(gAgentID, name); +		mAgentPanel->childSetValue("user_text", name); + +		mSpeakingIndicator = mAgentPanel->getChild<LLOutputMonitorCtrl>("speaking_indicator"); +		mSpeakingIndicator->setSpeakerId(gAgentID); +	} +} + +void LLCallFloater::setModeratorMutedVoice(bool moderator_muted) +{ +	mIsModeratorMutedVoice = moderator_muted; +	if (moderator_muted) +	{ +		LLNotificationsUtil::add("VoiceIsMutedByModerator"); +	} +	mSpeakingIndicator->setIsMuted(moderator_muted); +} + +void LLCallFloater::updateModeratorState() +{  	std::string name;  	gCacheName->getFullName(gAgentID, name); -	childSetValue("user_text", name); -	LLOutputMonitorCtrl* speaking_indicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); -	speaking_indicator->setSpeakerId(gAgentID); +	if(gAgent.isInGroup(mSpeakerManager->getSessionID())) +	{ +		// This method can be called when LLVoiceChannel.mState == STATE_NO_CHANNEL_INFO +		// in this case there are no any speakers yet. +		if (mSpeakerManager->findSpeaker(gAgentID)) +		{ +			// Agent is Moderator +			if (mSpeakerManager->findSpeaker(gAgentID)->mIsModerator) + +			{ +				const std::string moderator_indicator(LLTrans::getString("IM_moderator_label"));  +				name += " " + moderator_indicator; +			} +		} +	} +	mAgentPanel->childSetValue("user_text", name);  }  //EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index b615f57d5b..b2288a42ff 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -35,12 +35,13 @@  #define LL_LLCALLFLOATER_H  #include "lldockablefloater.h" +#include "llvoiceclient.h"  class LLAvatarList;  class LLNonAvatarCaller; +class LLOutputMonitorCtrl;  class LLParticipantList;  class LLSpeakerMgr; -  /**   * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron on the Speak button.   * It can be torn-off and freely positioned onscreen. @@ -52,7 +53,7 @@ class LLSpeakerMgr;   * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel also provides an    * 'Leave Call' button to allow the Resident to leave that voice channel.   */ -class LLCallFloater : public LLDockableFloater +class LLCallFloater : public LLDockableFloater, LLVoiceClientParticipantObserver  {  public:  	LLCallFloater(const LLSD& key); @@ -60,6 +61,14 @@ public:  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ void draw(); + +	/** +	 * Is called by LLVoiceClient::notifyParticipantObservers when voice participant list is changed. +	 * +	 * Refreshes list to display participants not in voice as disabled. +	 */ +	/*virtual*/ void onChange();  private:  	typedef enum e_voice_controls_type @@ -87,6 +96,8 @@ private:  	void onCurrentChannelChanged(const LLUUID& session_id);  	void updateTitle();  	void initAgentData(); +	void setModeratorMutedVoice(bool moderator_muted); +	void updateModeratorState();  private:  	LLSpeakerMgr* mSpeakerManager; @@ -94,6 +105,9 @@ private:  	LLAvatarList* mAvatarList;  	LLNonAvatarCaller* mNonAvatarCaller;  	EVoiceControls mVoiceType; +	LLPanel* mAgentPanel; +	LLOutputMonitorCtrl* mSpeakingIndicator; +	bool mIsModeratorMutedVoice;  	boost::signals2::connection mChannelChangedConnection;  }; diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 714bd20ab8..82413878ad 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -55,7 +55,6 @@  #include "llinventorymodel.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llresmgr.h"  #include "llimview.h"  #include "llviewercontrol.h" diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 415c118ff1..cbb566b3a7 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -228,3 +228,14 @@ void LLChannelManager::muteAllChannels(bool mute)  	}  } +void LLChannelManager::killToastsFromChannel(const LLUUID& channel_id, const LLScreenChannel::Matcher& matcher) +{ +	LLScreenChannel +			* screen_channel = +					dynamic_cast<LLScreenChannel*> (findChannelByID(channel_id)); +	if (screen_channel != NULL) +	{ +		screen_channel->killMatchedToasts(matcher); +	} +} + diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index 4b66a1ef89..c2be39122f 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -109,6 +109,11 @@ public:  	 */  	void muteAllChannels(bool mute); +	/** +	 * Kills matched toasts from specified  toast screen channel. +	 */ +	void killToastsFromChannel(const LLUUID& channel_id, const LLScreenChannel::Matcher& matcher); +  private:  	LLScreenChannel* createChannel(LLChannelManager::Params& p); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 6c843e1ec3..ee60df1b4b 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -49,6 +49,8 @@  static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history"); +const static std::string NEW_LINE(rawstr_to_utf8("\n")); +  class LLChatHistoryHeader: public LLPanel  {  public: @@ -454,10 +456,21 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  		if (chat.mFromName.size() > 0)  			appendText(chat.mFromName + " ", TRUE, style_params); -		appendText(chat.mText.substr(4), FALSE, style_params); +		// Ensure that message ends with NewLine, to avoid losing of new lines +		// while copy/paste from text chat. See EXT-3263. +		appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params);  	}  	else -		appendText(chat.mText, FALSE, style_params); +	{ +		std::string message(chat.mText); +		if ( message.size() > 0 && !LLStringOps::isSpace(message[message.size() - 1]) ) +		{ +			// Ensure that message ends with NewLine, to avoid losing of new lines +			// while copy/paste from text chat. See EXT-3263. +			message += NEW_LINE; +		} +		appendText(message, FALSE, style_params); +	}  	blockUndo();  } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 30967677e8..c7f77810df 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -53,6 +53,7 @@  #include "llgroupmgr.h"  #include "llnotificationmanager.h"  #include "lltransientfloatermgr.h" +#include "llsyswellwindow.h"  static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");  static LLDefaultChildRegistry::Register<LLIMWellChiclet> t2_0("chiclet_im_well"); @@ -88,6 +89,14 @@ class LLSysWellChiclet::FlashToLitTimer : public LLEventTimer  {  public:  	typedef boost::function<void()> callback_t; + +	/** +	 * Constructor. +	 * +	 * @param count - how many times callback should be called (twice to not change original state) +	 * @param period - how frequently callback should be called +	 * @param cb - callback to be called each tick +	 */  	FlashToLitTimer(S32 count, F32 period, callback_t cb)  		: LLEventTimer(period)  		, mCallback(cb) @@ -111,8 +120,17 @@ public:  		mEventTimer.start();  	} +	void stopFlashing() +	{ +		mEventTimer.stop(); +	} +  private:  	callback_t		mCallback; + +	/** +	 * How many times Well will blink. +	 */  	S32 mFlashCount;  	S32 mCurrentFlashCount;  }; @@ -134,6 +152,7 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p)  , mButton(NULL)  , mCounter(0)  , mMaxDisplayedCount(p.max_displayed_count) +, mIsNewMessagesState(false)  , mFlashToLitTimer(NULL)  {  	LLButton::Params button_params = p.button; @@ -163,20 +182,20 @@ void LLSysWellChiclet::setCounter(S32 counter)  	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); +	setNewMessagesState(counter > 0); -	if (mCounter == 0 && counter > 0) +	// we have to flash to 'Lit' state each time new unread message is comming. +	if (counter > mCounter)  	{  		mFlashToLitTimer->flash();  	} +	else if (counter == 0) +	{ +		// if notification is resolved while well is flashing it can leave in the 'Lit' state +		// when flashing finishes itself. Let break flashing here. +		mFlashToLitTimer->stopFlashing(); +	} +  	mCounter = counter;  } @@ -192,11 +211,22 @@ void LLSysWellChiclet::setToggleState(BOOL toggled) {  void LLSysWellChiclet::changeLitState()  { -	static bool set_lit = false; +	setNewMessagesState(!mIsNewMessagesState); +} -	mButton->setForcePressedState(set_lit); +void LLSysWellChiclet::setNewMessagesState(bool new_messages) +{ +	/* +	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(new_messages); -	set_lit ^= true; +	mIsNewMessagesState = new_messages;  }  /************************************************************************/ @@ -209,6 +239,8 @@ LLIMWellChiclet::LLIMWellChiclet(const Params& p)  	LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1));  	LLIMMgr::getInstance()->addSessionObserver(this); + +	LLIMWellWindow::getInstance()->setSysWellChiclet(this);  }  LLIMWellChiclet::~LLIMWellChiclet() @@ -233,6 +265,10 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p)  	connectCounterUpdatersToSignal("notify");  	connectCounterUpdatersToSignal("groupnotify");  	connectCounterUpdatersToSignal("offer"); + +	// ensure that notification well window exists, to synchronously +	// handle toast add/delete events. +	LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);  }  void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 65abcd1f5f..353fc01c34 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -791,6 +791,8 @@ public:  	void setToggleState(BOOL toggled); +	void setNewMessagesState(bool new_messages); +  protected:  	LLSysWellChiclet(const Params& p); @@ -809,11 +811,8 @@ protected:  	LLButton* mButton;  	S32 mCounter;  	S32 mMaxDisplayedCount; +	bool mIsNewMessagesState; -	/** -	 * How many times Well will blink. -	 */ -	S32 mFlashToLitCount;  	FlashToLitTimer* mFlashToLitTimer;  }; diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp index 411cb331a8..ead377deb0 100644 --- a/indra/newview/lldelayedgestureerror.cpp +++ b/indra/newview/lldelayedgestureerror.cpp @@ -36,7 +36,6 @@  #include <list>  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llcallbacklist.h"  #include "llinventory.h"  #include "llviewerinventory.h" diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index b64799bd86..edfb9dc864 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -37,7 +37,6 @@  #include "llnotificationsutil.h"  #include "message.h" -#include "llnotify.h"  #include "lleventinfo.h"  #include "llfloaterreg.h"  #include "llfloaterworldmap.h" diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp index 0bcdad5da1..7fd0e070be 100644 --- a/indra/newview/llfirstuse.cpp +++ b/indra/newview/llfirstuse.cpp @@ -40,7 +40,6 @@  // viewer includes  #include "llagent.h"	// for gAgent.inPrelude() -#include "llnotify.h"  #include "llviewercontrol.h"  #include "llui.h"  #include "llappviewer.h" diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index bbccbb8709..698ccec9c1 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -48,7 +48,6 @@  #include "llcombobox.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llsavedsettingsglue.h"  #include "llviewertexturelist.h"  #include "llviewerparcelmgr.h" diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index 16a5bb63e7..fba557c656 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -41,7 +41,6 @@  #include "llfloaterbuy.h"  #include "llagent.h"			// for agent id -#include "llalertdialog.h"  #include "llinventorymodel.h"	// for gInventory  #include "llfloaterreg.h"  #include "llfloaterinventory.h"	// for get_item_icon diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index 39c7bc02af..0daef27af2 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -43,7 +43,6 @@  #include "llcachename.h"  #include "llagent.h"			// for agent id -#include "llalertdialog.h"  #include "llcheckboxctrl.h"  #include "llinventoryfunctions.h"  #include "llinventorymodel.h"	// for gInventory diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 3a8c3ab4d2..9b88923e7e 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -49,7 +49,6 @@  #include "lliconctrl.h"  #include "lllineeditor.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llparcel.h"  #include "llslurl.h"  #include "llstatusbar.h" diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 1482d3fe21..56291c57a6 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -50,7 +50,6 @@  #include "llinventorymodel.h"  #include "llnamelistctrl.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llresmgr.h"  #include "llscrolllistctrl.h"  #include "llscrolllistitem.h" diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index 04ba11530a..e1409b8ad5 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -45,7 +45,6 @@  #include "message.h"  #include "llagent.h" -#include "llalertdialog.h"  #include "llbutton.h"  #include "llcheckboxctrl.h"  #include "llcombobox.h" @@ -69,7 +68,6 @@  #include "llviewerwindow.h"  #include "llworld.h"  #include "llfloateravatarpicker.h" -#include "llnotify.h"  #include "llxfermanager.h"  #include "llvlcomposition.h"  #include "llsurface.h" diff --git a/indra/newview/llfloaterhud.cpp b/indra/newview/llfloaterhud.cpp index 14cff3bcc3..d2ee3e44c5 100644 --- a/indra/newview/llfloaterhud.cpp +++ b/indra/newview/llfloaterhud.cpp @@ -37,7 +37,6 @@  // Viewer libs  #include "llviewercontrol.h"  #include "llmediactrl.h" -#include "llalertdialog.h"  // Linden libs  #include "llnotificationsutil.h" diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 5b03292b22..66bf5246b0 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -55,7 +55,6 @@  #include "llavataractions.h"  #include "lllineeditor.h"  #include "llnamelistctrl.h" -#include "llnotify.h"  #include "llpanellandaudio.h"  #include "llpanellandmedia.h"  #include "llradiogroup.h" diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index c1e8d251ee..bc89f93763 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -44,7 +44,6 @@  #include "llnotificationsutil.h"  #include "lltextbox.h" -#include "llalertdialog.h"  #include "llinventorybridge.h"  #include "llfloaterinventory.h"  #include "llinventorymodel.h" diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index 17bb8221ad..7edc27d4c3 100644 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -32,7 +32,6 @@   */  #include "llviewerprecompiledheaders.h" -#include "llalertdialog.h"  #include "llcheckboxctrl.h"  #include "llfloaterperms.h"  #include "llviewercontrol.h" diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index ab27375b87..a333868b8c 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -588,6 +588,9 @@ void LLFloaterPreference::onOpen(const LLSD& key)  	// when the floater is opened.  That will make cancel do its  	// job  	saveSettings(); + +	// This is a "fresh" floater, closing floater shoud cancel any changes +	mCancelOnClose = true;  }  void LLFloaterPreference::onVertexShaderEnable() @@ -633,7 +636,11 @@ void LLFloaterPreference::onBtnOK()  		// that prevents cancel from undoing our changes when we hit OK  		mCancelOnClose = false;  		closeFloater(false); -		mCancelOnClose = true; + +		// closeFloater() will be called when viewer is quitting, leaving mCancelOnClose = true; +		// will cancel all changes we saved here, don't let this happen. +		// Fix for EXT-3465 +  		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );  		LLUIColorTable::instance().saveUserSettings();  		std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 381f4ed508..496fa62d05 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -48,7 +48,6 @@  #include "message.h"  #include "llagent.h" -#include "llalertdialog.h"  #include "llappviewer.h"  #include "llfloateravatarpicker.h"  #include "llbutton.h"  @@ -63,7 +62,6 @@  #include "llfloaterwindlight.h"  #include "llinventorymodel.h"  #include "lllineeditor.h" -#include "llalertdialog.h"  #include "llnamelistctrl.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 49e8f9c956..e5260aa7b9 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -39,7 +39,6 @@  #include "lllineeditor.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llparcel.h"  #include "llselectmgr.h"  #include "lltexturectrl.h" diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 4f487ddf04..df7aa9eabf 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -52,7 +52,6 @@  #include "llagent.h"  #include "lldelayedgestureerror.h"  #include "llinventorymodel.h" -#include "llnotify.h"  #include "llviewermessage.h"  #include "llvoavatarself.h"  #include "llviewerstats.h" diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 4c7e71f040..ff75d461df 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -199,12 +199,12 @@ void LLGroupActions::activate(const LLUUID& group_id)  	gAgent.sendReliableMessage();  } -bool	isGroupUIVisible() +static bool isGroupUIVisible()  {  	LLPanel* panel = LLSideTray::getInstance()->findChild<LLPanel>("panel_group_info_sidetray");  	if(!panel)  		return false; -	return panel->getVisible(); +	return panel->isInVisibleChain();  }  // static diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 80b706a215..ab9db10f38 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -225,6 +225,11 @@ mGroupID(LLUUID::null)  	}  } +LLGroupListItem::~LLGroupListItem() +{ +	LLGroupMgr::getInstance()->removeObserver(this); +} +  //virtual  BOOL  LLGroupListItem::postBuild()  { @@ -277,8 +282,13 @@ void LLGroupListItem::setName(const std::string& name, const std::string& highli  void LLGroupListItem::setGroupID(const LLUUID& group_id)  { +	LLGroupMgr::getInstance()->removeObserver(this); +	 +	mID = group_id;  	mGroupID = group_id;  	setActive(group_id == gAgent.getGroupID()); + +	LLGroupMgr::getInstance()->addObserver(this);  }  void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id) @@ -337,4 +347,11 @@ void LLGroupListItem::onProfileBtnClick()  	LLGroupActions::show(mGroupID);  } +void LLGroupListItem::changed(LLGroupChange gc) +{ +	LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID); +	if(group_data) +		setGroupIconID(group_data->mInsigniaID); +} +  //EOF diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 41b4d01711..33cfe005b9 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -38,6 +38,7 @@  #include "llpanel.h"  #include "llpointer.h"  #include "llstyle.h" +#include "llgroupmgr.h"  /**   * Auto-updating list of agent groups. @@ -80,9 +81,11 @@ class LLIconCtrl;  class LLTextBox;  class LLGroupListItem : public LLPanel +	, public LLGroupMgrObserver  {  public:  	LLGroupListItem(); +	~LLGroupListItem();  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setValue(const LLSD& value);  	void onMouseEnter(S32 x, S32 y, MASK mask); @@ -96,6 +99,7 @@ public:  	void setGroupIconID(const LLUUID& group_icon_id);  	void setGroupIconVisible(bool visible); +	virtual void changed(LLGroupChange gc);  private:  	void setActive(bool active);  	void onInfoBtnClick(); diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index ebb5feb2bf..af58e81ca4 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -758,7 +758,8 @@ void LLGroupMgr::clearGroupData(const LLUUID& group_id)  void LLGroupMgr::addObserver(LLGroupMgrObserver* observer)   {  -	mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer)); +	if( observer->getID() != LLUUID::null ) +		mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer));  }  void LLGroupMgr::removeObserver(LLGroupMgrObserver* observer) diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index a0604be57e..487fdd4c5b 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -45,6 +45,7 @@ class LLGroupMgrObserver  {  public:  	LLGroupMgrObserver(const LLUUID& id) : mID(id){}; +	LLGroupMgrObserver() : mID(LLUUID::null){};  	virtual ~LLGroupMgrObserver(){};  	virtual void changed(LLGroupChange gc) = 0;  	const LLUUID& getID() { return mID; } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 47a168e354..7dc21e6e23 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -469,7 +469,7 @@ bool LLIMFloater::toggle(const LLUUID& session_id)  	if(!isChatMultiTab())  	{  		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -		if (floater && floater->getVisible() && floater->isDocked()) +		if (floater && floater->getVisible())  		{  			// clicking on chiclet to close floater just hides it to maintain existing  			// scroll/text entry state @@ -947,3 +947,20 @@ void LLIMFloater::initIMFloater()  	// init chat window type before user changed it in preferences  	isChatMultiTab();  } + +//static +void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) +{ +	LLUUID session_id = data["session_id"]; +	if (session_id.isNull()) return; + +	LLUUID from_id = data["from_id"]; +	if (gAgentID == from_id || LLUUID::null == from_id) return; + +	LLIMFloater* floater = LLIMFloater::findInstance(session_id); +	if (!floater) return; + +	if (IM_NOTHING_SPECIAL != floater->mDialog) return; + +	floater->removeTypingIndicator(); +} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index ab3e15c6b2..bc7a43e852 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -110,6 +110,9 @@ public:  	static void initIMFloater(); +	//used as a callback on receiving new IM message +	static void sRemoveTypingIndicator(const LLSD& data); +  private:  	// process focus events to set a currently active session  	/* virtual */ void onFocusLost(); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index e6ded5f371..8b6762ce38 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -66,7 +66,6 @@  #include "llimview.h"                  // for LLIMModel to get other avatar id in chat  #include "llkeyboard.h"  #include "lllineeditor.h" -#include "llnotify.h"  #include "llpanelimcontrolpanel.h"  #include "llrecentpeople.h"  #include "llresmgr.h" diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4d2ba16a4c..b50d4674f7 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -72,7 +72,6 @@  #include "llviewerwindow.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llnearbychat.h"  #include "llviewerregion.h"  #include "llvoicechannel.h" @@ -170,22 +169,39 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&  	mOtherParticipantIsAvatar(true),  	mStartCallOnInitialize(false)  { +	// set P2P type by default +	mSessionType = P2P_SESSION; +  	if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type)  	{  		mVoiceChannel  = new LLVoiceChannelP2P(session_id, name, other_participant_id); + +		// check if it was AVALINE call +		if (!mOtherParticipantIsAvatar) +		{ +			mSessionType = AVALINE_SESSION; +		}   	}  	else  	{  		mVoiceChannel = new LLVoiceChannelGroup(session_id, name); + +		// determine whether it is group or conference session +		if (gAgent.isInGroup(mSessionID)) +		{ +			mSessionType = GROUP_SESSION; +		} +		else +		{ +			mSessionType = ADHOC_SESSION; +		}   	}  	if(mVoiceChannel)  	{ -		mVoiceChannelStateChangeConnection = mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2)); +		mVoiceChannelStateChangeConnection = mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2, _3));  	} -	// define what type of session was opened -	setSessionType(); -	 +		  	mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);  	// All participants will be added to the list of people we've recently interacted with. @@ -218,45 +234,18 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&  	}  } -void LLIMModel::LLIMSession::setSessionType() -{ -	// set P2P type by default -	mSessionType = P2P_SESSION; - -	if (dynamic_cast<LLVoiceChannelP2P*>(mVoiceChannel) && !mOtherParticipantIsAvatar) // P2P AVALINE channel was opened -	{ -		mSessionType = AVALINE_SESSION; -		return; -	}  -	else if(dynamic_cast<LLVoiceChannelGroup*>(mVoiceChannel)) // GROUP channel was opened -	{ -		if (mType == IM_SESSION_CONFERENCE_START) -		{ -			mSessionType = ADHOC_SESSION; -			return; -		}  -		else if(mType == IM_SESSION_GROUP_START) -		{ -			mSessionType = GROUP_SESSION; -			return; -		}		 -	} -} - -void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction)  {  	// *TODO: remove hardcoded string!!!!!!!!!!!  	bool is_p2p_session = dynamic_cast<LLVoiceChannelP2P*>(mVoiceChannel); -	bool is_incoming_call = false;  	std::string other_avatar_name;  	if(is_p2p_session)  	{ -		is_incoming_call = static_cast<LLVoiceChannelP2P*>(mVoiceChannel)->isIncomingCall();  		gCacheName->getFullName(mOtherParticipantID, other_avatar_name); -		if(is_incoming_call) +		if(direction == LLVoiceChannel::INCOMING_CALL)  		{  			switch(new_state)  			{ @@ -1060,7 +1049,7 @@ public:  			if (LLIMMgr::INVITATION_TYPE_VOICE == mInvitiationType)  			{ -				gIMMgr->startCall(mSessionID); +				gIMMgr->startCall(mSessionID, LLVoiceChannel::INCOMING_CALL);  			}  			if ((mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE  @@ -1271,11 +1260,10 @@ void LLCallDialogManager::onVoiceChannelChanged(const LLUUID &session_id)  	sCurrentSessionlName = session->mName;  } -void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction)  {  	LLSD mCallDialogPayload;  	LLOutgoingCallDialog* ocd; -	bool is_incoming;  	mCallDialogPayload["session_id"] = sSession->mSessionID;  	mCallDialogPayload["session_name"] = sSession->mName; @@ -1286,9 +1274,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat  	{			  	case LLVoiceChannel::STATE_CALL_STARTED :  		// 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) +		if(direction == LLVoiceChannel::INCOMING_CALL)  		{  			return;  		} @@ -1470,6 +1456,7 @@ BOOL LLOutgoingCallDialog::postBuild()  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLIncomingCallDialog  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +  LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) :  LLCallDialog(payload)  { @@ -1479,26 +1466,34 @@ BOOL LLIncomingCallDialog::postBuild()  {  	LLDockableFloater::postBuild(); +	LLUUID session_id = mPayload["session_id"].asUUID();  	LLSD caller_id = mPayload["caller_id"]; -	EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger(); - -	std::string call_type = getString("VoiceInviteP2P");  	std::string caller_name = mPayload["caller_name"].asString(); +	 +	std::string call_type; +	if (gAgent.isInGroup(session_id)) +	{ +		LLStringUtil::format_map_t args; +		LLGroupData data; +		if (gAgent.getGroupData(session_id, data)) +		{ +			args["[GROUP]"] = data.mName; +			call_type = getString(mPayload["notify_box_type"], args); +		} +	} +	else +	{ +		call_type = getString(mPayload["notify_box_type"]); +	} +		  	if (caller_name == "anonymous")  	{  		caller_name = getString("anonymous");  	}  	setTitle(caller_name + " " + call_type); -	 -	// If it is not a P2P invite, then it's an AdHoc invite -	if ( type != IM_SESSION_P2P_INVITE ) -	{ -		call_type = getString("VoiceInviteAdHoc"); -	}  	// check to see if this is an Avaline call -	LLUUID session_id = mPayload["session_id"].asUUID();  	bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id);  	childSetVisible("Start IM", is_avatar); // no IM for avaline @@ -1587,7 +1582,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response)  			if (voice)  			{ -				if (gIMMgr->startCall(session_id)) +				if (gIMMgr->startCall(session_id, LLVoiceChannel::INCOMING_CALL))  				{  					// always open IM window when connecting to voice  					LLIMFloater::show(session_id); @@ -1798,6 +1793,8 @@ LLIMMgr::LLIMMgr() :  {  	mPendingInvitations = LLSD::emptyMap();  	mPendingAgentListUpdates = LLSD::emptyMap(); + +	LLIMModel::getInstance()->addNewMsgCallback(boost::bind(&LLIMFloater::sRemoveTypingIndicator, _1));  }  // Add a message to a session.  @@ -2438,11 +2435,12 @@ void LLIMMgr::removeSessionObserver(LLIMSessionObserver *observer)  	mSessionObservers.remove(observer);  } -bool LLIMMgr::startCall(const LLUUID& session_id) +bool LLIMMgr::startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction)  {  	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);  	if (!voice_channel) return false; +	voice_channel->setCallDirection(direction);  	voice_channel->activate();  	return true;  } diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index f26889ac91..e2fcd63e28 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -69,10 +69,9 @@ public:  		virtual ~LLIMSession();  		void sessionInitReplyReceived(const LLUUID& new_session_id); -		void setSessionType(); //define what type of session was opened  		void addMessagesFromHistory(const std::list<LLSD>& history);  		void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time); -		void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); +		void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);  		static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);  		LLUUID mSessionID; @@ -384,7 +383,7 @@ public:  	 * Start call in a session  	 * @return false if voice channel doesn't exist  	 **/ -	bool startCall(const LLUUID& session_id); +	bool startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction = LLVoiceChannel::OUTGOING_CALL);  	/**  	 * End call in a session @@ -448,7 +447,7 @@ public:  	static void initClass();  	static void onVoiceChannelChanged(const LLUUID &session_id); -	static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); +	static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);  protected:  	static std::string sPreviousSessionlName; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e361082f7b..e2f9663000 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3014,7 +3014,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			// everything in the active window so that we don't follow  			// the selection to its new location (which is very  			// annoying). -			LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); +			LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);  			if (active_panel)  			{  				LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index d613cf6ba4..bd9d22c327 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -39,7 +39,6 @@  #include "llappviewer.h"  #include "llagent.h" -#include "llnotify.h"  #include "llvfile.h"  #include "llviewerstats.h" diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index 28ddaa61c4..a2aef9ba63 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -49,7 +49,6 @@  #include "llfloaterchat.h"  #include "llfloaterworldmap.h"  #include "lllineeditor.h" -#include "llnotify.h"  #include "llstatusbar.h"  #include "llimview.h"  #include "lltextbox.h" diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index c17427bec1..22201aecb2 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -160,9 +160,12 @@ void LLFloaterMove::setEnabled(BOOL enabled)  // virtual  void LLFloaterMove::setVisible(BOOL visible)  { -	// Ignore excessive calls of this method (from LLTransientFloaterMgr?). +	// Do nothing with Stand/Stop Flying panel in excessive calls of this method (from LLTransientFloaterMgr?).  	if (getVisible() == visible) +	{ +		LLTransientDockableFloater::setVisible(visible);  		return; +	}  	if (visible)  	{ diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index b9f422ca6f..ffe7f57167 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -396,7 +396,7 @@ void LLPanelProfileTab::updateButtons()  					&& gAgent.isGodlike() || is_agent_mappable(getAvatarId());  	childSetEnabled("show_on_map_btn", enable_map_btn); -	childSetEnabled("call", LLVoiceClient::voiceEnabled()); +	childSetEnabled("call", LLAvatarActions::canCall(getAvatarId()));  }  ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 70d92442ad..0dae667e7f 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -48,7 +48,6 @@  #include "message.h"  #include "llagent.h" -#include "llalertdialog.h"  #include "llavataractions.h"  #include "llbutton.h"  #include "llcheckboxctrl.h" diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index b6c58808ae..29b647415c 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -44,7 +44,6 @@  #include "llnamelistctrl.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llpanelgrouproles.h"  #include "llscrolllistctrl.h"  #include "llscrolllistitem.h" diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index a5bfa18851..a9c604b72a 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -62,7 +62,6 @@  #include "llviewermenu.h"			// for handle_preferences()  #include "llviewernetwork.h"  #include "llviewerwindow.h"			// to link into child list -#include "llnotify.h"  #include "llurlsimstring.h"  #include "lluictrlfactory.h"  #include "llhttpclient.h" diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 5fb7dab7be..e134840153 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -586,6 +586,7 @@ BOOL LLPanelPeople::postBuild()  	registrar.add("People.Groups.ViewSort.Action",  boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked,  this, _2));  	registrar.add("People.Recent.ViewSort.Action",  boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked,  this, _2)); +	enable_registrar.add("People.Group.Minus.Enable",	boost::bind(&LLPanelPeople::isRealGroup,	this));  	enable_registrar.add("People.Friends.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck,	this, _2));  	enable_registrar.add("People.Recent.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck,	this, _2));  	enable_registrar.add("People.Nearby.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck,	this, _2)); @@ -775,7 +776,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 && LLVoiceClient::voiceEnabled()); +	buttonSetEnabled("call_btn",			multiple_selected && canCall());  	buttonSetEnabled("share_btn",			item_selected); // not implemented yet  	bool none_group_selected = item_selected && selected_id.isNull(); @@ -783,6 +784,29 @@ void LLPanelPeople::updateButtons()  	buttonSetEnabled("chat_btn", !none_group_selected);  } +bool LLPanelPeople::canCall() +{ +	std::vector<LLUUID> selected_uuids; +	getCurrentItemIDs(selected_uuids); + +	bool result = false; + +	std::vector<LLUUID>::const_iterator +		id = selected_uuids.begin(), +		uuids_end = selected_uuids.end(); + +	for (;id != uuids_end; ++id) +	{ +		if (LLAvatarActions::canCall(*id)) +		{ +			result = true; +			break; +		} +	} + +	return result; +} +  std::string LLPanelPeople::getActiveTabName() const  {  	return mTabContainer->getCurrentPanel()->getName(); @@ -921,6 +945,11 @@ void LLPanelPeople::reSelectedCurrentTab()  	mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());  } +bool LLPanelPeople::isRealGroup() +{ +	return getCurrentItemID() != LLUUID::null; +} +  void LLPanelPeople::onFilterEdit(const std::string& search_string)  {  	std::string search_upper = search_string; diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index a9cc6d0ccb..f5cdc0935c 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -73,6 +73,7 @@ private:  	bool					isFriendOnline(const LLUUID& id);  	bool					isItemsFreeOfFriends(const std::vector<LLUUID>& uuids); +	bool 					canCall();  	void					updateButtons();  	std::string				getActiveTabName() const; @@ -118,6 +119,8 @@ private:  	void					onGroupsViewSortMenuItemClicked(const LLSD& userdata);  	void					onRecentViewSortMenuItemClicked(const LLSD& userdata); +	//returns false only if group is "none" +	bool					isRealGroup();  	bool					onFriendsViewSortMenuItemCheck(const LLSD& userdata);  	bool					onRecentViewSortMenuItemCheck(const LLSD& userdata);  	bool					onNearbyViewSortMenuItemCheck(const LLSD& userdata); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 04fe42de9f..0314642d9e 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -81,6 +81,14 @@ void ContextMenu::show(LLView* spawning_view, const std::vector<LLUUID>& uuids,  	LLMenuGL::showPopup(spawning_view, mMenu, x, y);  } +void ContextMenu::hide() +{ +	if(mMenu) +	{ +		mMenu->hide(); +	} +} +  //== NearbyMenu ===============================================================  LLContextMenu* NearbyMenu::createMenu() @@ -173,7 +181,25 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)  		const LLUUID& id = mUUIDs.front();  		return LLAvatarActions::isFriend(id);  	} +	else if (item == std::string("can_call")) +	{ +		bool result = false; +		int size = mUUIDs.size(); +		std::cout << size << std::endl; +		std::vector<LLUUID>::const_iterator +			id = mUUIDs.begin(), +			uuids_end = mUUIDs.end(); +		for (;id != uuids_end; ++id) +		{ +			if (LLAvatarActions::canCall(*id)) +			{ +				result = true; +				break; +			} +		} +		return result; +	}  	return false;  } diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h index ed0f8208f6..14ae2985f0 100644 --- a/indra/newview/llpanelpeoplemenus.h +++ b/indra/newview/llpanelpeoplemenus.h @@ -54,6 +54,8 @@ public:  	 */  	/*virtual*/ void show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y); +	virtual void hide(); +  protected:  	virtual LLContextMenu* createMenu() = 0; diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 541361324a..839452d061 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -91,12 +91,19 @@ LLPanelPickInfo::LLPanelPickInfo()   , mAvatarId(LLUUID::null)   , mSnapshotCtrl(NULL)   , mPickId(LLUUID::null) + , mParcelId(LLUUID::null) + , mRequestedId(LLUUID::null)  {  }  LLPanelPickInfo::~LLPanelPickInfo()  {  	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); + +	if (mParcelId.notNull()) +	{ +		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); +	}  }  void LLPanelPickInfo::onOpen(const LLSD& key) @@ -156,12 +163,14 @@ void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type)  		return;  	} +	mParcelId = pick_info->parcel_id;  	setSnapshotId(pick_info->snapshot_id);  	setPickName(pick_info->name);  	setPickDesc(pick_info->desc);  	setPosGlobal(pick_info->pos_global); -	setPickLocation(createLocationText(pick_info->user_name, pick_info->original_name,  -		pick_info->sim_name, pick_info->pos_global)); + +	// Send remote parcel info request to get parcel name and sim (region) name. +	sendParcelInfoRequest();  	// *NOTE dzaporozhan  	// We want to keep listening to APT_PICK_INFO because user may  @@ -169,6 +178,17 @@ void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type)  	// revomeObserver is called from onClickBack  } +void LLPanelPickInfo::sendParcelInfoRequest() +{ +	if (mParcelId != mRequestedId) +	{ +		LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this); +		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId); + +		mRequestedId = mParcelId; +	} +} +  void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb)  {  	getChild<LLButton>("back_btn")->setClickedCallback(cb); @@ -176,21 +196,16 @@ void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb)  void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data)  { -	// HACK: Flag 0x2 == adult region, -	// Flag 0x1 == mature region, otherwise assume PG -	std::string rating_icon = "icon_event.tga"; -	if (parcel_data.flags & 0x2) -	{ -		rating_icon = "icon_event_adult.tga"; -	} -	else if (parcel_data.flags & 0x1) -	{ -		rating_icon = "icon_event_mature.tga"; -	} +	setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name, +		parcel_data.sim_name, getPosGlobal())); -	childSetValue("maturity", rating_icon); +	// We have received parcel info for the requested ID so clear it now. +	mRequestedId.setNull(); -	//*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us +	if (mParcelId.notNull()) +	{ +		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); +	}  }  void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb) @@ -222,7 +237,8 @@ void LLPanelPickInfo::resetData()  	setPickId(LLUUID::null);  	setSnapshotId(LLUUID::null);  	mPosGlobal.clearVec(); -	childSetValue("maturity", LLStringUtil::null); +	mParcelId.setNull(); +	mRequestedId.setNull();  }  // static @@ -273,9 +289,6 @@ void LLPanelPickInfo::setPickDesc(const std::string& desc)  void LLPanelPickInfo::setPickLocation(const std::string& location)  {  	childSetValue(XML_LOCATION, location); - -	//preserving non-wrapped text for info/edit modes switching -	mLocation = location;  }  void LLPanelPickInfo::onClickMap() @@ -340,7 +353,7 @@ void LLPanelPickEdit::onOpen(const LLSD& key)  		setPosGlobal(gAgent.getPositionGlobal());  		LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null; -		std::string pick_name, pick_desc; +		std::string pick_name, pick_desc, region_name;  		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();  		if(parcel) @@ -351,21 +364,17 @@ void LLPanelPickEdit::onOpen(const LLSD& key)  			snapshot_id = parcel->getSnapshotID();  		} -		if(pick_name.empty()) +		LLViewerRegion* region = gAgent.getRegion(); +		if(region)  		{ -			LLViewerRegion* region = gAgent.getRegion(); -			if(region) -			{ -				pick_name = region->getName(); -			} +			region_name = region->getName();  		}  		setParcelID(parcel_id); -		childSetValue("pick_name", pick_name); +		childSetValue("pick_name", pick_name.empty() ? region_name : pick_name);  		childSetValue("pick_desc", pick_desc);  		setSnapshotId(snapshot_id); -		setPickLocation(createLocationText(LLStringUtil::null, SET_LOCATION_NOTICE,  -			pick_name, getPosGlobal())); +		setPickLocation(createLocationText(SET_LOCATION_NOTICE, pick_name, region_name, getPosGlobal()));  		enableSaveButton(true);  	} @@ -394,8 +403,9 @@ void LLPanelPickEdit::setPickData(const LLPickData* pick_data)  	childSetValue("pick_name", pick_data->name);  	childSetValue("pick_desc", pick_data->desc);  	setSnapshotId(pick_data->snapshot_id); -	setPickLocation(createLocationText(pick_data->user_name, pick_data->original_name, /*pick_data->sim_name,*/  -		pick_data->name, pick_data->pos_global)); +	setPosGlobal(pick_data->pos_global); +	setPickLocation(createLocationText(LLStringUtil::null, pick_data->name, +			pick_data->sim_name, pick_data->pos_global));  }  BOOL LLPanelPickEdit::postBuild() @@ -519,14 +529,22 @@ void LLPanelPickEdit::onClickSetLocation()  	// Save location for later use.  	setPosGlobal(gAgent.getPositionGlobal()); +	std::string parcel_name, region_name; +  	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();  	if (parcel)  	{  		mParcelId = parcel->getID(); -		mSimName = parcel->getName(); +		parcel_name = parcel->getName();  	} -	setPickLocation(createLocationText( -		LLStringUtil::null, SET_LOCATION_NOTICE, mSimName, getPosGlobal())); + +	LLViewerRegion* region = gAgent.getRegion(); +	if(region) +	{ +		region_name = region->getName(); +	} + +	setPickLocation(createLocationText(SET_LOCATION_NOTICE, parcel_name, region_name, getPosGlobal()));  	mLocationChanged = true;  	enableSaveButton(TRUE); diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 2c0830f2ac..95add387d0 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -72,6 +72,11 @@ public:  	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type);  	/** +	 * Sends remote parcel info request to resolve parcel name from its ID. +	 */ +	void sendParcelInfoRequest(); + +	/**  	 * Sets "Back" button click callback  	 */  	virtual void setExitCallback(const commit_callback_t& cb); @@ -81,9 +86,9 @@ public:  	 */  	virtual void setEditPickCallback(const commit_callback_t& cb); -	//This stuff we got from LLRemoteParcelObserver, in the last two we intentionally do nothing +	//This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing  	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); -	/*virtual*/ void setParcelID(const LLUUID& parcel_id) {}; +	/*virtual*/ void setParcelID(const LLUUID& parcel_id) { mParcelId = parcel_id; }  	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason) {};  protected: @@ -154,8 +159,7 @@ protected:  	LLVector3d mPosGlobal;  	LLUUID mParcelId;  	LLUUID mPickId; -	std::string mSimName; -	std::string mLocation; +	LLUUID mRequestedId;  };  /** diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index b845f38ace..b80eb9db38 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -233,8 +233,10 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)  	if (!parcel_data.name.empty())  	{ +		mParcelTitle = parcel_data.name; +  		mParcelName->setText(llformat("%s (%d, %d, %d)", -							 parcel_data.name.c_str(), region_x, region_y, region_z)); +							 mParcelTitle.c_str(), region_x, region_y, region_z));  	}  	else  	{ @@ -284,15 +286,12 @@ void LLPanelPlaceInfo::handleVisibilityChange(BOOL new_visibility)  void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel)  { -	std::string name = mParcelName->getText(); -	if (name.empty()) -	{ -		name = mRegionName->getText(); -	} +	std::string region_name = mRegionName->getText();  	LLPickData data;  	data.pos_global = pos_global; -	data.name = name; +	data.name = mParcelTitle.empty() ? region_name : mParcelTitle; +	data.sim_name = region_name;  	data.desc = mDescEditor->getText();  	data.snapshot_id = mSnapshotCtrl->getImageAssetID();  	data.parcel_id = mParcelID; diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index b9bf92b534..7dfc7b2444 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -111,6 +111,7 @@ protected:  	LLUUID					mParcelID;  	LLUUID					mRequestedID;  	LLVector3				mPosRegion; +	std::string				mParcelTitle; // used for pick title without coordinates  	std::string				mCurrentTitle;  	S32						mScrollingPanelMinHeight;  	S32						mScrollingPanelWidth; diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 43f80f6d6a..596bd2909a 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -505,7 +505,7 @@ void LLTeleportHistoryPanel::refresh()  			tab->setVisible(true);  			// Expand all accordion tabs when filtering -			if(!mFilterSubString.empty()) +			if(!sFilterSubString.empty())  			{  				tab->setDisplayChildren(true);  			} @@ -521,7 +521,7 @@ void LLTeleportHistoryPanel::refresh()  		if (curr_flat_view)  		{ -			LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle, mFilterSubString); +			LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle, sFilterSubString);  			curr_flat_view->addItem(item);  			if (mLastSelectedItemIndex == mCurrentItem) @@ -569,7 +569,7 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)  	LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(history_items.size(), // index will be decremented inside loop below  									&mContextMenu,  									history_items[history_items.size() - 1].mTitle, // Most recent item, it was -									mFilterSubString); +									sFilterSubString);  															 // added instead of removed  	fv->addItem(item, LLUUID::null, ADD_TOP); diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index f646fea355..0c0f891f32 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -109,7 +109,6 @@ private:  	S32				mLastSelectedItemIndex;  	bool				mDirty;  	S32				mCurrentItem; -	std::string				mFilterSubString;  	typedef LLDynamicArray<LLAccordionCtrlTab*> item_containers_t;  	item_containers_t mItemContainers; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 48a7a32a3b..2c5f1b094e 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -42,11 +42,50 @@  #include "llavatarlist.h"  #include "llspeakers.h"  #include "llviewermenu.h" +#include "llvoiceclient.h"  //LLParticipantList retrieves add, clear and remove events and updates view accordingly   #if LL_MSVC  #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally  #endif + +class ModerationResponder : public LLHTTPClient::Responder +{ +public: +	ModerationResponder(const LLUUID& session_id) +	{ +		mSessionID = session_id; +	} + +	virtual void error(U32 status, const std::string& reason) +	{ +		llwarns << status << ": " << reason << llendl; + +		if ( gIMMgr ) +		{ +			//403 == you're not a mod +			//should be disabled if you're not a moderator +			if ( 403 == status ) +			{ +				gIMMgr->showSessionEventError( +					"mute", +					"not_a_mod_error", +					mSessionID); +			} +			else +			{ +				gIMMgr->showSessionEventError( +					"mute", +					"generic_request_error", +					mSessionID); +			} +		} +	} + +private: +	LLUUID mSessionID; +}; +  LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list,  bool use_context_menu/* = true*/):  	mSpeakerMgr(data_source),  	mAvatarList(avatar_list), @@ -57,6 +96,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av  	mSpeakerRemoveListener = new SpeakerRemoveListener(*this);  	mSpeakerClearListener = new SpeakerClearListener(*this);  	mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this); +	mSpeakerMuteListener = new SpeakerMuteListener(*this);  	mSpeakerMgr->addListener(mSpeakerAddListener, "add");  	mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove"); @@ -87,6 +127,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av  	for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)  	{  		const LLPointer<LLSpeaker>& speakerp = *it; +  		addAvatarIDExceptAgent(group_members, speakerp->mID);  		if ( speakerp->mIsModerator )  		{ @@ -103,6 +144,14 @@ LLParticipantList::~LLParticipantList()  	mAvatarListRefreshConnection.disconnect();  	mAvatarListReturnConnection.disconnect(); +	// It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged() +	// See ticket EXT-3427 +	// hide menu before deleting it to stop enable and check handlers from triggering. +	if(mParticipantListMenu) +	{ +		mParticipantListMenu->hide(); +	} +  	delete mParticipantListMenu;  	mParticipantListMenu = NULL;  } @@ -184,6 +233,27 @@ void LLParticipantList::setSortOrder(EParticipantSortOrder order)  	}  } +void LLParticipantList::refreshVoiceState() +{ +	LLSpeakerMgr::speaker_list_t speakers; +	mSpeakerMgr->getSpeakerList(&speakers, TRUE); + +	for (LLSpeakerMgr::speaker_list_t::iterator iter = speakers.begin(); +		iter != speakers.end(); ++iter) +	{ +		LLSpeaker* speakerp = (*iter).get(); +		const LLUUID& speaker_id = speakerp->mID; +		LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (mAvatarList->getItemByValue(speaker_id)); +		if ( item ) +		{ +			// if voice is disabled for this speaker show non voice speakers as disabled +			bool is_in_voice = speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE +				&& speakerp->mStatus != LLSpeaker::STATUS_MUTED; +			item->setOnline(!is_in_voice); +		} +	} +} +  bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)  {  	LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); @@ -248,6 +318,24 @@ bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> e  	return true;  } +bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ +	LLPointer<LLSpeaker> speakerp = (LLSpeaker*)event->getSource(); +	if (speakerp.isNull()) return false; + +	// update UI on confirmation of moderator mutes +	if (event->getValue().asString() == "voice") +	{ +		LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mAvatarList->getItemByValue(speakerp->mID)); +		if (item) +		{ +			LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); +			indicator->setIsMuted(speakerp->mModeratorMutedVoice); +		} +	} +	return true; +} +  void LLParticipantList::sort()  {  	if ( !mAvatarList ) @@ -264,13 +352,21 @@ void LLParticipantList::sort()  	}  } -// static  void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id)  { -	if (gAgent.getID() != avatar_id) -	{ -		existing_list.push_back(avatar_id); -	} +	if (gAgent.getID() == avatar_id) return; + +	existing_list.push_back(avatar_id); +	adjustParticipant(avatar_id); +} + +void LLParticipantList::adjustParticipant(const LLUUID& speaker_id) +{ +	LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(speaker_id); +	if (speakerp.isNull()) return; + +	// add listener to process moderation changes +	speakerp->addListener(mSpeakerMuteListener);  }  // @@ -315,6 +411,11 @@ bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LL  		return mParent.onModeratorUpdateEvent(event, userdata);  } +bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ +	return mParent.onSpeakerMuteEvent(event, userdata); +} +  LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  {  	// set up the callbacks for all of the avatar menu items @@ -324,14 +425,27 @@ 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("Avatar.Profile",	boost::bind(&LLAvatarActions::showProfile, mUUIDs.front())); +	registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, mUUIDs.front())); +	registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs.front())); +	registrar.add("Avatar.BlockUnblock", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteVoice, this, _2)); +	registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, mUUIDs.front())); +	registrar.add("Avatar.Pay",	boost::bind(&LLAvatarActions::pay, mUUIDs.front())); +	registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, mUUIDs.front())); +  	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));  	// create the context menu from the XUI -	return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( +	LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(  		"menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); + +	main_menu->setItemVisible("Moderator Options", isGroupModerator()); +	main_menu->arrangeAndClear(); + +	return main_menu;  }  void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y) @@ -341,7 +455,7 @@ void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const  	if (uuids.size() == 0) return;  	const LLUUID speaker_id = mUUIDs.front(); -	BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, LLMute::flagVoiceChat); +	BOOL is_muted = isMuted(speaker_id);  	if (is_muted)  	{ @@ -353,7 +467,6 @@ void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const  		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false);  		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false);  	} -  }  void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata) @@ -370,47 +483,10 @@ void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& u  	//current value represents ability to type, so invert  	data["params"]["mute_info"]["text"] = !mParent.mSpeakerMgr->findSpeaker(speaker_id)->mModeratorMutedText; -	class MuteTextResponder : public LLHTTPClient::Responder -	{ -	public: -		MuteTextResponder(const LLUUID& session_id) -		{ -			mSessionID = session_id; -		} - -		virtual void error(U32 status, const std::string& reason) -		{ -			llwarns << status << ": " << reason << llendl; - -			if ( gIMMgr ) -			{ -				//403 == you're not a mod -				//should be disabled if you're not a moderator -				if ( 403 == status ) -				{ -					gIMMgr->showSessionEventError( -						"mute", -						"not_a_moderator", -						mSessionID); -				} -				else -				{ -					gIMMgr->showSessionEventError( -						"mute", -						"generic", -						mSessionID); -				} -			} -		} - -	private: -		LLUUID mSessionID; -	}; -  	LLHTTPClient::post(  		url,  		data, -		new MuteTextResponder(mParent.mSpeakerMgr->getSessionID())); +		new ModerationResponder(mParent.mSpeakerMgr->getSessionID()));  }  void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, U32 flags) @@ -450,36 +526,87 @@ void LLParticipantList::LLParticipantListMenu::toggleMuteVoice(const LLSD& userd  	toggleMute(userdata, LLMute::flagVoiceChat);  } +bool LLParticipantList::LLParticipantListMenu::isGroupModerator() +{ +	// Agent is in Group Call +	if(gAgent.isInGroup(mParent.mSpeakerMgr->getSessionID())) +	{ +		// Agent is Moderator +		return mParent.mSpeakerMgr->findSpeaker(gAgentID)->mIsModerator; +	} +	return false; +} + +bool LLParticipantList::LLParticipantListMenu::isMuted(const LLUUID& avatar_id) +{ +	LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(avatar_id); +	if (!selected_speakerp) return true; + +	return selected_speakerp->mStatus == LLSpeaker::STATUS_MUTED; +} +  void LLParticipantList::LLParticipantListMenu::moderateVoice(const LLSD& userdata)  { +	if (!gAgent.getRegion()) return; +	bool moderate_selected = userdata.asString() == "selected"; +	const LLUUID& selected_avatar_id = mUUIDs.front(); +	bool is_muted = isMuted(selected_avatar_id); + +	if (moderate_selected) +	{ +		moderateVoiceParticipant(selected_avatar_id, is_muted); +	} +	else +	{ +		moderateVoiceOtherParticipants(selected_avatar_id, is_muted); +	}  } -void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(const LLSD& userdata) + +void LLParticipantList::LLParticipantListMenu::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute) +{ +	if (gAgentID == avatar_id) return; // do not process myself + +	LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(avatar_id); +	if (!speakerp) return; + +	// *NOTE: mantipov: probably this condition will be incorrect when avatar will be blocked for +	// text chat via moderation (LLSpeaker::mModeratorMutedText == TRUE) +	bool is_in_voice = speakerp->mStatus <= LLSpeaker::STATUS_VOICE_ACTIVE || speakerp->mStatus == LLSpeaker::STATUS_MUTED; + +	// do not send voice moderation changes for avatars not in voice channel +	if (!is_in_voice) return; + +	std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); +	LLSD data; +	data["method"] = "mute update"; +	data["session-id"] = mParent.mSpeakerMgr->getSessionID(); +	data["params"] = LLSD::emptyMap(); +	data["params"]["agent_id"] = avatar_id; +	data["params"]["mute_info"] = LLSD::emptyMap(); +	data["params"]["mute_info"]["voice"] = !unmute; + +	LLHTTPClient::post( +		url, +		data, +		new ModerationResponder(mParent.mSpeakerMgr->getSessionID())); +} + +void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute)  {  	LLSpeakerMgr::speaker_list_t speakers; -	mParent.mSpeakerMgr->getSpeakerList(&speakers, true); +	mParent.mSpeakerMgr->getSpeakerList(&speakers, FALSE); -	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 (excluded_avatar_id == speaker_id) continue; -		if (should_mute) -		{ -			LLMuteList::getInstance()->add(mute, LLMute::flagVoiceChat); -		} -		else -		{ -			LLMuteList::getInstance()->remove(mute, LLMute::flagVoiceChat); -		} +		moderateVoiceParticipant(speaker_id, unmute);  	} -  }  bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata) @@ -492,9 +619,35 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD&  	else  		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; +			return isGroupModerator(); +		} +	else if (item == std::string("can_add")) +		{ +			// We can add friends if: +			// - there are selected people +			// - and there are no friends among selection yet. + +			bool result = (mUUIDs.size() > 0); + +			std::vector<LLUUID>::const_iterator +				id = mUUIDs.begin(), +				uuids_end = mUUIDs.end(); + +			for (;id != uuids_end; ++id) +			{ +				if ( LLAvatarActions::isFriend(*id) ) +				{ +					result = false; +					break; +				} +			} +			return result;  		} +	else if (item == "can_call") +	{ +		return LLVoiceClient::voiceEnabled(); +	} +  	return true;  } @@ -502,17 +655,26 @@ bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD&  {  	std::string item = userdata.asString();  	const LLUUID& id = mUUIDs.front(); +  	if (item == "is_muted") -		return LLMuteList::getInstance()->isMuted(id, LLMute::flagTextChat);  -	else -		if (item == "is_allowed_text_chat") -		{ -			LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(id); +	{ +		return LLMuteList::getInstance()->isMuted(id, LLMute::flagTextChat); +	} +	else if (item == "is_allowed_text_chat") +	{ +		LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(id); -			if (selected_speakerp.notNull()) -			{ -				return !selected_speakerp->mModeratorMutedText; -			} +		if (selected_speakerp.notNull()) +		{ +			return !selected_speakerp->mModeratorMutedText;  		} +	} +	else if(item == "is_blocked") +	{ +		return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); +	} +  	return false;  } + +//EOF diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 83191a5b8d..bc6c6c2b50 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -52,10 +52,16 @@ class LLParticipantList  		} EParticipantSortOrder;  		/** -		  * Set and sort Avatarlist by given order -		  */ +		 * Set and sort Avatarlist by given order +		 */  		void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); +		/** +		 * Refreshes participants to display ones not in voice as disabled. +		 * TODO: mantipov: probably should be moved into derived class for LLFloaterCall +		 */ +		void refreshVoiceState(); +  	protected:  		/**  		 * LLSpeakerMgr event handlers @@ -64,6 +70,7 @@ class LLParticipantList  		bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);  		bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);  		bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); +		bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);  		/**  		 * Sorts the Avatarlist by stored order @@ -109,6 +116,14 @@ class LLParticipantList  			/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);  		}; +		class SpeakerMuteListener : public BaseSpeakerListner +		{ +		public: +			SpeakerMuteListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} + +			/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); +		}; +  		/**  		 * Menu used in the participant list.  		 */ @@ -129,9 +144,55 @@ class LLParticipantList  			void toggleMuteText(const LLSD& userdata);  			void toggleMuteVoice(const LLSD& userdata); +			/** +			 * Return true if Agent is group moderator(and moderator of group call). +			 */ +			bool isGroupModerator(); +  			// Voice moderation support +			/** +			 * Check whether specified by argument avatar is muted for group chat or not. +			 */ +			bool isMuted(const LLUUID& avatar_id); + +			/** +			 * Processes Voice moderation menu items. +			 * +			 * It calls either moderateVoiceParticipant() or moderateVoiceParticipant() depend on +			 * passed parameter. +			 * +			 * @param userdata can be "selected" or "others". +			 * +			 * @see moderateVoiceParticipant() +			 * @see moderateVoiceOtherParticipants() +			 */  			void moderateVoice(const LLSD& userdata); -			void moderateVoiceOtherParticipants(const LLSD& userdata); + +			/** +			 * Mutes/Unmutes avatar for current group voice chat. +			 * +			 * It only marks avatar as muted for session and does not use local Agent's Block list. +			 * It does not mute Agent itself. +			 * +			 * @param[in] avatar_id UUID of avatar to be processed +			 * @param[in] unmute if true - specified avatar will be muted, otherwise - unmuted. +			 * +			 * @see moderateVoiceOtherParticipants() +			 */ +			void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); + +			/** +			 * Mutes/Unmutes all avatars except specified for current group voice chat. +			 * +			 * It only marks avatars as muted for session and does not use local Agent's Block list. +			 * It based call moderateVoiceParticipant() for each avatar should be muted/unmuted. +			 * +			 * @param[in] excluded_avatar_id UUID of avatar NOT to be processed +			 * @param[in] unmute if true - avatars will be muted, otherwise - unmuted. +			 * +			 * @see moderateVoiceParticipant() +			 */ +			void moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute);  		};  	private: @@ -140,8 +201,18 @@ class LLParticipantList  		/**  		 * Adds specified avatar ID to the existing list if it is not Agent's ID +		 * +		 * @param[in, out] existing_list - vector with avatars' UUIDs already in the list +		 * @param[in] avatar_id - Avatar UUID to be added into the list +		 */ +		void addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id); + +		/** +		 * Adjusts passed participant to work properly. +		 * +		 * Adds SpeakerMuteListener to process moderation actions.  		 */ -		static void addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id); +		void adjustParticipant(const LLUUID& speaker_id);  		LLSpeakerMgr*		mSpeakerMgr;  		LLAvatarList*		mAvatarList; @@ -153,6 +224,7 @@ class LLParticipantList  		LLPointer<SpeakerRemoveListener>			mSpeakerRemoveListener;  		LLPointer<SpeakerClearListener>				mSpeakerClearListener;  		LLPointer<SpeakerModeratorUpdateListener>	mSpeakerModeratorListener; +		LLPointer<SpeakerMuteListener>				mSpeakerMuteListener;  		LLParticipantListMenu*    mParticipantListMenu; diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 30cb21c83c..f1891aa421 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -59,7 +59,6 @@  #include "llinventorymodel.h"  #include "llkeyboard.h"  #include "lllineeditor.h" -#include "llnotify.h"  #include "llradiogroup.h"  #include "llscrolllistctrl.h"  #include "llscrolllistitem.h" diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 5d675fcda6..95756ac5f3 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -44,7 +44,6 @@  #include "llinventorymodel.h"  #include "lllineeditor.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llresmgr.h"  #include "roles_constants.h"  #include "llscrollbar.h" diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 8d80310769..646c9fb6a4 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -61,7 +61,6 @@  #include "llvfile.h"  #include "llagent.h" -#include "llnotify.h"  #include "llmenugl.h"  #include "roles_constants.h"  #include "llselectmgr.h" diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index f66f725070..bd256ec9c2 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -151,21 +151,49 @@ LLScreenChannel::~LLScreenChannel()  } +std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) +{ +	std::list<LLToast*> res; + +	// collect stored toasts +	for (std::vector<ToastElem>::iterator it = mStoredToastList.begin(); it +			!= mStoredToastList.end(); it++) +	{ +		if (matcher.matches(it->toast->getNotification())) +		{ +			res.push_back(it->toast); +		} +	} + +	// collect displayed toasts +	for (std::vector<ToastElem>::iterator it = mToastList.begin(); it +			!= mToastList.end(); it++) +	{ +		if (matcher.matches(it->toast->getNotification())) +		{ +			res.push_back(it->toast); +		} +	} + +	return res; +} +  //--------------------------------------------------------------------------  void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect 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 : +		this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio());  		break;  	case CA_CENTRE : -		this_rect.setCenterAndSize(new_world_rect.getWidth() / 2, new_world_rect.getHeight() / 2, this_rect.getWidth(), this_rect.getHeight()); -		break; +		LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect); +		return;  	case CA_RIGHT : +		this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio());  		this_rect.mLeft -= right_delta;  		this_rect.mRight -= right_delta;  	} @@ -375,6 +403,16 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)  	}  } +void LLScreenChannel::killMatchedToasts(const Matcher& matcher) +{ +	std::list<LLToast*> to_delete = findToasts(matcher); +	for (std::list<LLToast*>::iterator it = to_delete.begin(); it +			!= to_delete.end(); it++) +	{ +		killToastByNotificationID((*it)-> getNotificationID()); +	} +} +  //--------------------------------------------------------------------------  void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)  { @@ -776,17 +814,19 @@ void LLScreenChannel::updateShowToastsState()  		return;  	} -	// *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) || dynamic_cast<LLIMFloater*>(floater)) +	if(dynamic_cast<LLSysWellWindow*>(floater) || dynamic_cast<LLIMFloater*>(floater) +		|| dynamic_cast<LLScriptFloater*>(floater))  	{  		S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;  		LLRect this_rect = getRect();  		if(floater->getVisible() && floater->isDocked())  		{  			channel_bottom += floater->getRect().getHeight(); -			channel_bottom += floater->getDockControl()->getTongueHeight(); +			if(floater->getDockControl()) +			{ +				channel_bottom += floater->getDockControl()->getTongueHeight(); +			}  		}  		if(channel_bottom != this_rect.mBottom) diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index b8efbb148f..321fb244a1 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -151,6 +151,16 @@ public:  	LLScreenChannel(LLUUID& id);  	virtual ~LLScreenChannel(); +	class Matcher +	{ +	public: +		Matcher(){} +		virtual ~Matcher() {} +		virtual bool matches(const LLNotificationPtr) const = 0; +	}; + +	std::list<LLToast*> findToasts(const Matcher& matcher); +  	// Channel's outfit-functions  	// update channel's size and position in the World View  	void		updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect); @@ -162,6 +172,7 @@ public:  	void		addToast(const LLToast::Params& p);  	// kill or modify a toast by its ID  	void		killToastByNotificationID(LLUUID id); +	void		killMatchedToasts(const Matcher& matcher);  	void		modifyToastByNotificationID(LLUUID id, LLPanel* panel);  	// hide all toasts from screen, but not remove them from a channel  	void		hideToastsFromScreen(); diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 5c4f6e8860..1962d871a6 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -66,6 +66,7 @@ LLScriptFloater::LLScriptFloater(const LLSD& key)  : LLDockableFloater(NULL, true, key)  , mScriptForm(NULL)  { +	setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this));  }  bool LLScriptFloater::toggle(const LLUUID& object_id) @@ -180,6 +181,23 @@ void LLScriptFloater::setVisible(BOOL visible)  	hideToastsIfNeeded();  } +void LLScriptFloater::onMouseDown() +{ +	if(getObjectId().notNull()) +	{ +		// Remove new message icon +		LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getObjectId()); +		if (chiclet == NULL) +		{ +			llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); +		} +		else +		{ +			chiclet->setShowNewMessagesIcon(false); +		} +	} +} +  void LLScriptFloater::hideToastsIfNeeded()  {  	using namespace LLNotificationsUI; @@ -191,6 +209,7 @@ void LLScriptFloater::hideToastsIfNeeded()  	if(channel)  	{  		channel->updateShowToastsState(); +		channel->redrawToasts();  	}  } @@ -217,11 +236,18 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)  	script_notification_map_t::iterator it = mNotifications.find(object_id);  	if(it != mNotifications.end())  	{ +		LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(object_id); +		if(chiclet) +		{ +			// Pass the new_message icon state further. +			set_new_message = chiclet->getShowNewMessagesIcon(); +		} +  		LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->second.notification_id);  		if(floater)  		{ -			// Generate chiclet with a "new message" indicator if a docked window was opened. See EXT-3142. -			set_new_message = floater->isShown(); +			// Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142. +			set_new_message |= !floater->hasFocus();  		}  		onRemoveNotification(it->second.notification_id); diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h index 95ec5a4d9c..ed10dc5fe9 100644 --- a/indra/newview/llscriptfloater.h +++ b/indra/newview/llscriptfloater.h @@ -169,6 +169,11 @@ protected:  	 */  	static void hideToastsIfNeeded(); +	/** +	 * Removes chiclets new messages icon +	 */ +	void onMouseDown(); +  private:  	LLToastNotifyPanel* mScriptForm;  	LLUUID mObjectId; diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index a1af2e5411..608165022f 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -354,8 +354,7 @@ LLButton* LLSideTray::createButton	(const std::string& name,const std::string& i  	button->setLabel(name);  	button->setClickedCallback(callback); -	if(tooltip!="Home") -		button->setToolTip(tooltip); +	button->setToolTip(tooltip);  	if(image.length())  	{ diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 93655eb1f1..539673ab9e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -121,7 +121,6 @@  #include "lllogininstance.h" // Host the login module.  #include "llpanellogin.h"  #include "llmutelist.h" -#include "llnotify.h"  #include "llpanelavatar.h"  #include "llavatarpropertiesprocessor.h"  #include "llpanelevent.h" diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 4915720036..9e72464237 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -50,7 +50,6 @@  #include "llkeyboard.h"  #include "lllineeditor.h"  #include "llmenugl.h" -#include "llnotify.h"  #include "llimview.h"  #include "llsd.h"  #include "lltextbox.h" diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 1ebf624eeb..ea49f9c32e 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -51,6 +51,7 @@  LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key),  													mChannel(NULL),  													mMessageList(NULL), +													mSysWellChiclet(NULL),  													mSeparator(NULL),  													NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"),  													IM_WELL_ANCHOR_NAME("im_well_panel") @@ -80,6 +81,10 @@ BOOL LLSysWellWindow::postBuild()  	mMessageList->addItem(mSeparator); +	// click on SysWell Window should clear "new message" state (and 'Lit' status). EXT-3147. +	// mouse up callback is not called in this case. +	setMouseDownCallback(boost::bind(&LLSysWellWindow::releaseNewMessagesState, this)); +  	return LLDockableFloater::postBuild();  } @@ -174,6 +179,11 @@ void LLSysWellWindow::setVisible(BOOL visible)  		mChannel->updateShowToastsState();  		mChannel->redrawToasts();  	} + +	if (visible) +	{ +		releaseNewMessagesState(); +	}  }  //--------------------------------------------------------------------------------- @@ -227,6 +237,14 @@ void LLSysWellWindow::reshapeWindow()  	}  } +void LLSysWellWindow::releaseNewMessagesState() +{ +	if (NULL != mSysWellChiclet) +	{ +		mSysWellChiclet->setNewMessagesState(false); +	} +} +  //---------------------------------------------------------------------------------  bool LLSysWellWindow::isWindowEmpty()  { @@ -246,6 +264,24 @@ void LLSysWellWindow::handleItemAdded(EItemType added_item_type)  		// refresh list to recalculate mSeparator position  		mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight());  	} + +	//fix for EXT-3254 +	//set limits for min_height.  +	S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight(); + +	std::vector<LLPanel*> items; +	mMessageList->getItems(items); + +	if(items.size()>1)//first item is separator +	{ +		S32 min_height; +		S32 min_width; +		getResizeLimits(&min_width,&min_height); + +		min_height = items[1]->getRect().getHeight() + 2 * mMessageList->getBorderWidth() + parent_list_delta_height; + +		setResizeLimits(min_width,min_height); +	}  }  void LLSysWellWindow::handleItemRemoved(EItemType removed_item_type) @@ -752,6 +788,13 @@ void LLIMWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,  //---------------------------------------------------------------------------------  void LLIMWellWindow::delIMRow(const LLUUID& sessionId)  { +	//fix for EXT-3252 +	//without this line LLIMWellWindow receive onFocusLost +	//and hide itself. It was becaue somehow LLIMChicklet was in focus group for +	//LLIMWellWindow... +	//But I didn't find why this happen.. +	gFocusMgr.clearLastFocusForGroup(this); +  	if (mMessageList->removeItemByValue(sessionId))  	{  		handleItemRemoved(IT_INSTANT_MESSAGE); @@ -771,6 +814,10 @@ void LLIMWellWindow::delIMRow(const LLUUID& sessionId)  	{  		setVisible(FALSE);  	} +	else +	{ +		setFocus(true); +	}  }  void LLIMWellWindow::addObjectRow(const LLUUID& object_id, bool new_message/* = false*/) diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 43b2723df0..fea145a17e 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -47,6 +47,7 @@ class LLFlatListView;  class LLChiclet;  class LLIMChiclet;  class LLScriptChiclet; +class LLSysWellChiclet;  class LLSysWellWindow : public LLDockableFloater @@ -78,6 +79,8 @@ public:  	void onStartUpToastClick(S32 x, S32 y, MASK mask); +	void setSysWellChiclet(LLSysWellChiclet* chiclet) { mSysWellChiclet = chiclet; } +  	// size constants for the window and for its elements  	static const S32 MAX_WINDOW_HEIGHT		= 200;  	static const S32 MIN_WINDOW_WIDTH		= 318; @@ -104,12 +107,18 @@ protected:  	virtual const std::string& getAnchorViewName() = 0;  	void reshapeWindow(); +	void releaseNewMessagesState();  	// pointer to a corresponding channel's instance  	LLNotificationsUI::LLScreenChannel*	mChannel;  	LLFlatListView*	mMessageList;  	/** +	 * Reference to an appropriate Well chiclet to release "new message" state. EXT-3147 +	 */ +	LLSysWellChiclet* mSysWellChiclet; + +	/**  	 *	Special panel which is used as separator of Notifications & IM Rows.  	 *	It is always presents in the list and shown when it is necessary.  	 *	It should be taken into account when reshaping and checking list size diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 4131e2755a..2a56b2cd3a 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -72,6 +72,8 @@ LLToast::LLToast(const LLToast::Params& p)  {  	LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL); +	setCanDrag(FALSE); +  	if(mPanel)  	{  		insertPanel(mPanel); diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 0c3c598704..3d25fd4f02 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -139,6 +139,7 @@ public:  	// set whether this toast considered as hidden or not  	void setIsHidden( bool is_toast_hidden ) { mIsHidden = is_toast_hidden; } +	const LLNotificationPtr& getNotification() { return mNotification;}  	// Registers signals/callbacks for events  	toast_signal_t mOnFadeSignal; diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index a4f5164a8d..c48301fa1e 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -30,10 +30,6 @@   * $/LicenseInfo$   */ -// *NOTE: this module is a copy-paste of llui/llalertdialog.h -// Can we re-implement this as a subclass of LLAlertDialog and -// avoid all this code duplication? It already caused EXT-2232. -  #include "llviewerprecompiledheaders.h" // must be first include  #include "linden_common.h" @@ -60,7 +56,7 @@ const F32 DEFAULT_BUTTON_DELAY = 0.5f;  const S32 MSG_PAD = 8;  /*static*/ LLControlGroup* LLToastAlertPanel::sSettings = NULL; -/*static*/ LLAlertURLLoader* LLToastAlertPanel::sURLLoader; +/*static*/ LLToastAlertPanel::URLLoader* LLToastAlertPanel::sURLLoader;  //-----------------------------------------------------------------------------  // Private methods diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index 38a635e8a4..875ab82c54 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -30,10 +30,6 @@   * $/LicenseInfo$   */ -// *NOTE: this module is a copy-paste of llui/llalertdialog.h -// Can we re-implement this as a subclass of LLAlertDialog and -// avoid all this code duplication? It already caused EXT-2232. -  #ifndef LL_TOASTALERTPANEL_H  #define LL_TOASTALERTPANEL_H @@ -41,11 +37,9 @@  #include "llfloater.h"  #include "llui.h"  #include "llnotificationptr.h" -#include "llalertdialog.h"  class LLButton;  class LLCheckBoxCtrl; -class LLAlertDialogTemplate;  class LLLineEditor;  /** @@ -62,7 +56,16 @@ class LLToastAlertPanel  public:  	typedef bool (*display_callback_t)(S32 modal); -	static void setURLLoader(LLAlertURLLoader* loader) +	class URLLoader +	{ +	public: +		virtual void load(const std::string& url, bool force_open_externally = 0) = 0; +		virtual ~URLLoader() +		{ +		} +	}; + +	static void setURLLoader(URLLoader* loader)  	{  		sURLLoader = loader;  	} @@ -95,7 +98,7 @@ private:  	BOOL hasTitleBar() const;  private: -	static LLAlertURLLoader* sURLLoader; +	static URLLoader* sURLLoader;  	static LLControlGroup* sSettings;  	struct ButtonData diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index eacc077a65..e49044cdca 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -40,7 +40,6 @@  #include "lliconctrl.h"  #include "llinventoryfunctions.h"  #include "llnotifications.h" -#include "llnotify.h"  #include "llviewertexteditor.h"  #include "lluiconstants.h" diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 6339d23fa7..f3db0ab170 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -63,7 +63,6 @@  #include "llviewerjoystick.h"  #include "llviewerparcelmgr.h"  #include "llparcel.h" -#include "llnotify.h"  #include "lloverlaybar.h"  #include "llkeyboard.h"  #include "llerrorcontrol.h" @@ -516,34 +515,13 @@ bool toggle_show_snapshot_button(const LLSD& newvalue)  bool toggle_show_navigation_panel(const LLSD& newvalue)  { -	LLRect floater_view_rect = gFloaterView->getRect(); -	LLRect notify_view_rect = gNotifyBoxView->getRect(); -	LLNavigationBar* navbar = LLNavigationBar::getInstance(); -	 -	//if newvalue contains 0 => navbar should turn invisible, so floater_view_rect should get higher,  -	//and to do this pm=1, else if navbar becomes visible pm=-1 so floater_view_rect gets lower. -	int pm=newvalue.asBoolean()?-1:1; -	floater_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight()); -	notify_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight()); -	gFloaterView->setRect(floater_view_rect); -	floater_view_rect = gFloaterView->getRect(); -	navbar->showNavigationPanel(newvalue.asBoolean()); +	LLNavigationBar::getInstance()->showNavigationPanel(newvalue.asBoolean());  	return true;  }  bool toggle_show_favorites_panel(const LLSD& newvalue)  { -	LLRect floater_view_rect = gFloaterView->getRect(); -	LLRect notify_view_rect = gNotifyBoxView->getRect(); -	LLNavigationBar* navbar = LLNavigationBar::getInstance(); -	 -	//if newvalue contains 0 => favbar should turn invisible, so floater_view_rect should get higher,  -	//and to do this pm=1, else if favbar becomes visible pm=-1 so floater_view_rect gets lower. -	int pm=newvalue.asBoolean()?-1:1; -	floater_view_rect.mTop += pm*navbar->getDefFavBarHeight(); -	notify_view_rect.mTop += pm*navbar->getDefFavBarHeight(); -	gFloaterView->setRect(floater_view_rect); -	navbar->showFavoritesPanel(newvalue.asBoolean()); +	LLNavigationBar::getInstance()->showFavoritesPanel(newvalue.asBoolean());  	return true;  } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 8dcd1b8f93..5605f425e0 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -43,7 +43,6 @@  #include "llviewercontrol.h"  #include "llconsole.h"  #include "llinventorymodel.h" -#include "llnotify.h"  #include "llgesturemgr.h"  #include "llinventorybridge.h" diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5286fc0c59..ea40f2aae1 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -65,7 +65,6 @@  #include "llnearbychat.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llpanelgrouplandmoney.h"  #include "llpanelplaces.h"  #include "llrecentpeople.h" @@ -932,34 +931,40 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f  void inventory_offer_mute_callback(const LLUUID& blocked_id,  								   const std::string& first_name,  								   const std::string& last_name, -								   BOOL is_group) +								   BOOL is_group, LLOfferInfo* offer = NULL)  {  	std::string from_name;  	LLMute::EType type; -  	if (is_group)  	{  		type = LLMute::GROUP;  		from_name = first_name;  	} +	else if(offer && offer->mFromObject) +	{ +		//we have to block object by name because blocked_id is an id of owner +		type = LLMute::BY_NAME; +		from_name = offer->mFromName; +	}  	else  	{  		type = LLMute::AGENT;  		from_name = first_name + " " + last_name;  	} -	LLMute mute(blocked_id, from_name, type); +	// id should be null for BY_NAME mute, see  LLMuteList::add for details   +	LLMute mute(type == LLMute::BY_NAME ? LLUUID::null : blocked_id, from_name, type);  	if (LLMuteList::getInstance()->add(mute))  	{  		LLPanelBlockedList::showPanelAndSelect(blocked_id);  	}  	// purge the message queue of any previously queued inventory offers from the same source. -	class OfferMatcher : public LLNotifyBoxView::Matcher +	class OfferMatcher : public LLNotificationsUI::LLScreenChannel::Matcher  	{  	public:  		OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {} -		BOOL matches(const LLNotificationPtr notification) const +		bool matches(const LLNotificationPtr notification) const  		{  			if(notification->getName() == "ObjectGiveItem"   				|| notification->getName() == "ObjectGiveItemUnknownUser" @@ -972,7 +977,9 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id,  	private:  		const LLUUID& blocked_id;  	}; -	gNotifyBoxView->purgeMessagesMatching(OfferMatcher(blocked_id)); + +	LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel(LLUUID( +			gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(blocked_id));  }  LLOfferInfo::LLOfferInfo(const LLSD& sd) @@ -1068,7 +1075,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	// * we can't build two messages at once.  	if (2 == button)  	{ -		gCacheName->get(mFromID, mFromGroup, &inventory_offer_mute_callback); +		gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this));  	}  	std::string from_string; // Used in the pop-up. @@ -1202,7 +1209,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const  	// * we can't build two messages at once.  	if (2 == button)  	{ -		gCacheName->get(mFromID, mFromGroup, &inventory_offer_mute_callback); +		gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this));  	}  	LLMessageSystem* msg = gMessageSystem; @@ -1479,6 +1486,8 @@ void inventory_offer_handler(LLOfferInfo* info)  		// Note: sets inventory_task_offer_callback as the callback  		p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_task_offer_callback, info, _1, _2));  		p.name = name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser"; +		// Pop up inv offer chiclet and let the user accept (keep), or reject (and silently delete) the inventory. +		LLNotifications::instance().add(p);  	}  	else // Agent -> Agent Inventory Offer  	{ @@ -1502,18 +1511,14 @@ void inventory_offer_handler(LLOfferInfo* info)  		// In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages).  		info->send_auto_receive_response(); -	} -	// Pop up inv offer notification and let the user accept (keep), or reject (and silently delete) the inventory. -	LLNotifications::instance().add(p); - -	// TODO(EM): Recheck this after we will know how script notifications should look like. -	// Inform user that there is a script floater via toast system -	// { -	// 	payload["give_inventory_notification"] = TRUE; -	// 	LLNotificationPtr notification = LLNotifications::instance().add(p.payload(payload));  -	// 	LLScriptFloaterManager::getInstance()->setNotificationToastId(object_id, notification->getID()); -	// } +		// Inform user that there is a script floater via toast system +		{ +			payload["give_inventory_notification"] = TRUE; +			LLNotificationPtr notification = LLNotifications::instance().add(p.payload(payload));  +			LLScriptFloaterManager::getInstance()->setNotificationToastId(object_id, notification->getID()); +		} +	}  }  bool lure_callback(const LLSD& notification, const LLSD& response) @@ -4837,24 +4842,25 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)  		LLMuteList::getInstance()->add(LLMute(item_id, notification["payload"]["object_name"].asString(), LLMute::OBJECT));  		// purge the message queue of any previously queued requests from the same source. DEV-4879 -		class OfferMatcher : public LLNotifyBoxView::Matcher +		class OfferMatcher : public LLNotificationsUI::LLScreenChannel::Matcher  		{  		public:  			OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {} -			BOOL matches(const LLNotificationPtr notification) const +			bool matches(const LLNotificationPtr notification) const  			{  				if (notification->getName() == "ScriptQuestionCaution"  					|| notification->getName() == "ScriptQuestion")  				{  					return (notification->getPayload()["item_id"].asUUID() == blocked_id);  				} -				return FALSE; +				return false;  			}  		private:  			const LLUUID& blocked_id;  		}; -		// should do this via the channel -		gNotifyBoxView->purgeMessagesMatching(OfferMatcher(item_id)); + +		LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel(LLUUID( +				gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(item_id));  	}  	if (response["Details"]) @@ -5298,6 +5304,7 @@ void send_group_notice(const LLUUID& group_id,  bool handle_lure_callback(const LLSD& notification, const LLSD& response)  {  	std::string text = response["message"].asString(); +	text.append("\r\n").append(LLAgentUI::buildSLURL());  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);  	if(0 == option) diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 7a1abfd4e8..be68a2ef42 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -54,7 +54,6 @@  #include "llfloatergroups.h"  #include "llfloatersellland.h"  #include "llfloatertools.h" -#include "llnotify.h"  #include "llparcelselection.h"  #include "llresmgr.h"  #include "llsdutil.h" diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index e0091145ce..300aea1620 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -51,7 +51,6 @@  #include "llmenugl.h"  #include "llnotecard.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llpanelplaces.h"  #include "llpreview.h"  #include "llpreviewnotecard.h" diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 43eb3071dd..9cacdaa3f9 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -83,7 +83,6 @@  // newview includes  #include "llagent.h" -#include "llalertdialog.h"  #include "llbox.h"  #include "llconsole.h"  #include "llviewercontrol.h" @@ -130,7 +129,6 @@  #include "llmorphview.h"  #include "llmoveview.h"  #include "llnavigationbar.h" -#include "llnotify.h"  #include "lloverlaybar.h"  #include "llpreviewtexture.h"  #include "llprogressview.h" @@ -1453,7 +1451,6 @@ void LLViewerWindow::initBase()  	gDebugView = getRootView()->getChild<LLDebugView>("DebugView");  	gDebugView->init(); -	gNotifyBoxView = getRootView()->getChild<LLNotifyBoxView>("notify_container");  	gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view");  	// Add the progress bar view (startup view), which overrides everything @@ -1532,12 +1529,12 @@ void LLViewerWindow::initWorldUI()  	if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))  	{ -		toggle_show_navigation_panel(LLSD(0)); +		navbar->showNavigationPanel(FALSE);  	}  	if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"))  	{ -		toggle_show_favorites_panel(LLSD(0)); +		navbar->showFavoritesPanel(FALSE);  	}  	if (!gSavedSettings.getBOOL("ShowCameraButton")) @@ -1631,8 +1628,6 @@ void LLViewerWindow::shutdownViews()  	gMorphView = NULL;  	gHUDView = NULL; - -	gNotifyBoxView = NULL;  }  void LLViewerWindow::shutdownGL() @@ -2000,9 +1995,6 @@ void LLViewerWindow::draw()  #if LL_DEBUG  	LLView::sIsDrawing = FALSE;  #endif -	 -	// UI post-draw Updates -	gNotifyBoxView->updateNotifyBoxView();	  }  // Takes a single keydown event, usually when UI is visible @@ -2598,7 +2590,6 @@ void LLViewerWindow::updateUI()  				else if (dynamic_cast<LLUICtrl*>(viewp)   						&& viewp != gMenuHolder  						&& viewp != gFloaterView -						&& viewp != gNotifyBoxView  						&& viewp != gConsole)   				{  					if (dynamic_cast<LLFloater*>(viewp)) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 954e1d4469..6e93bf1bf2 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -65,7 +65,6 @@  #include "llkeyframewalkmotion.h"  #include "llmutelist.h"  #include "llmoveview.h" -#include "llnotify.h"  #include "llquantize.h"  #include "llregionhandle.h"  #include "llresmgr.h" diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 175b6f1d10..fd4e7bb91f 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -122,6 +122,7 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& sess  	mSessionID(session_id),   	mState(STATE_NO_CHANNEL_INFO),   	mSessionName(session_name), +	mCallDirection(OUTGOING_CALL),  	mIgnoreNextSessionLeave(FALSE)  {  	mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName; @@ -405,7 +406,7 @@ void LLVoiceChannel::doSetState(const EState& new_state)  	EState old_state = mState;  	mState = new_state;  	if (!mStateChangedCallback.empty()) -		mStateChangedCallback(old_state, mState); +		mStateChangedCallback(old_state, mState, mCallDirection);  }  //static diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 1bed329ba2..77801142cb 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -52,7 +52,13 @@ public:  		STATE_CONNECTED  	} EState; -	typedef boost::signals2::signal<void(const EState& old_state, const EState& new_state)> state_changed_signal_t; +	typedef enum e_voice_channel_direction +	{ +		INCOMING_CALL, +		OUTGOING_CALL +	} EDirection; + +	typedef boost::signals2::signal<void(const EState& old_state, const EState& new_state, const EDirection& direction)> state_changed_signal_t;  	// on current channel changed signal  	typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t; @@ -87,6 +93,9 @@ public:  	void updateSessionID(const LLUUID& new_session_id);  	const LLSD& getNotifyArgs() { return mNotifyArgs; } +	void setCallDirection(EDirection direction) {mCallDirection = direction;} +	EDirection getCallDirection() {return mCallDirection;} +  	static LLVoiceChannel* getChannelByID(const LLUUID& session_id);  	static LLVoiceChannel* getChannelByURI(std::string uri);  	static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; } @@ -103,6 +112,9 @@ protected:  	void doSetState(const EState& state);  	void setURI(std::string uri); +	// there can be two directions ICOMING and OUTGOING +	EDirection mCallDirection; +  	std::string	mURI;  	std::string	mCredentials;  	LLUUID		mSessionID; @@ -175,9 +187,6 @@ public:  	void setSessionHandle(const std::string& handle, const std::string &inURI); -	// returns TRUE if call is incoming and FALSE otherwise -	BOOL isIncomingCall() { return mReceivedCall; } -  protected:  	virtual void setState(EState state); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index aa69b46857..1889ca78c3 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -4271,7 +4271,6 @@ 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()) @@ -6346,20 +6345,6 @@ 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 edfe0173f8..347fae6156 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -527,8 +527,6 @@ 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/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index 31047413ef..bd7619f7e5 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -41,7 +41,6 @@  #include "llviewerinventory.h"  #include "llviewerstats.h"  #include "llnotificationsutil.h" -#include "llnotify.h"  #include "llinventorymodel.h"  #include "lltrans.h" diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 045bef294e..18f61501dc 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -52,7 +52,7 @@  #include "llviewernetwork.h"  #include "llviewerwindow.h" -class URLLoader : public LLAlertURLLoader +class URLLoader : public LLToastAlertPanel::URLLoader  {  	virtual void load(const std::string& url , bool force_open_externally)  	{ @@ -72,7 +72,6 @@ static URLLoader sAlertURLLoader;  // static  void LLWeb::initClass()  { -	LLAlertDialog::setURLLoader(&sAlertURLLoader);  	LLToastAlertPanel::setURLLoader(&sAlertURLLoader);  } 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 acd59b6f09..81c54ae55e 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -26,6 +26,10 @@       name="VoiceInviteAdHoc">          has joined a Voice Chat call with a conference chat.      </floater.string> +    <floater.string +     name="VoiceInviteGroup"> +        has joined a Voice Chat call with the group [GROUP]. +    </floater.string>      <avatar_icon       enabled="false"       follows="left|top" 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 0422972cd4..449202aaaa 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml @@ -16,7 +16,7 @@          <menu_item_call.on_click           function="Avatar.AddFriend" />          <menu_item_call.on_enable -         function="Avatar.EnableItem" +         function="ParticipantList.EnableItem"           parameter="can_add" />      </menu_item_call>      <menu_item_call @@ -30,11 +30,14 @@       label="Call"       layout="topleft"       name="Call"> -        <menu_item_call.on_click +         <menu_item_call.on_click           function="Avatar.Call" /> +        <menu_item_call.on_enable +         function="ParticipantList.EnableItem" +         parameter="can_call" />      </menu_item_call>      <menu_item_call -     enabled="false" +     enabled="true"       label="Share"       layout="topleft"       name="Share"> @@ -49,22 +52,22 @@           function="Avatar.Pay" />      </menu_item_call>      <menu_item_check -     label="Block/Unblock" +     label="Block Voice"       layout="topleft"       name="Block/Unblock">          <menu_item_check.on_click           function="Avatar.BlockUnblock" />          <menu_item_check.on_check -         function="Avatar.CheckItem" +         function="ParticipantList.CheckItem"           parameter="is_blocked" />          <menu_item_check.on_enable -         function="Avatar.EnableItem" +         function="ParticipantList.EnableItem"           parameter="can_block" />      </menu_item_check>          <menu_item_separator           layout="topleft" />      <menu_item_check -     label="Mute Text" +     label="Block Text"       layout="topleft"       name="MuteText">          <on_check @@ -76,6 +79,10 @@           function="ParticipantList.EnableItem"           parameter="can_mute_text" />      </menu_item_check> +    <context_menu +     label="Moderator Options >" +     layout="topleft" +     name="Moderator Options" >      <menu_item_check       label="Allow text chat"       layout="topleft" @@ -136,4 +143,5 @@           function="ParticipantList.EnableItem"           parameter="can_moderate_voice" />      </menu_item_call> +    </context_menu>  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml index 304492bedb..df3cb26b04 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml @@ -19,5 +19,7 @@     name="Leave Selected Group">        <menu_item_call.on_click         function="People.Group.Minus.Action"/> +      <menu_item_call.on_enable +       function="People.Group.Minus.Enable"/>    </menu_item_call>  </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 39469f7101..5f2e6e0f6c 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -32,6 +32,9 @@       name="Call">          <menu_item_call.on_click           function="Avatar.Call" /> +        <menu_item_call.on_enable +         function="Avatar.EnableItem" +         parameter="can_call" />      </menu_item_call>      <menu_item_call       label="Share" diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml index df74d2dcd4..0d3dd3366d 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml @@ -27,6 +27,9 @@       name="Call">          <on_click           function="Avatar.Call" /> +        <on_enable +         function="Avatar.EnableItem" +         parameter="can_call" />      </menu_item_call>      <menu_item_call       enabled="false" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 4645bfea74..bcf006f1a0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5014,13 +5014,13 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O         name="Keep"         text="Keep"/>        <button -       index="4" -       name="Show" -       text="Show"/>  -      <button         index="1"         name="Discard"         text="Discard"/> +      <button +       index="2" +       name="Mute" +       text="Block"/>      </form>    </notification> diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index c24f47750b..d4a6c7f3b3 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -77,6 +77,7 @@ background_visible="true"           layout="topleft"           left="5"           name="teleport_btn" +         tool_tip="Teleport to the selected area"           top="0"           width="100" />          <button @@ -86,6 +87,7 @@ background_visible="true"           layout="topleft"           left_pad="5"           name="map_btn" +         tool_tip="Show selected area on the map"           top="0"           width="70" />          <button diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml index 32fc9fce01..06da64533b 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml @@ -151,7 +151,7 @@          <button           follows="bottom|left"           font="SansSerifBigBold" -         tool_tip="" +         tool_tip="Show additional optioins"           height="18"           image_disabled="OptionsMenu_Disabled"           image_selected="OptionsMenu_Press" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 1f7784d9ab..2f50c5ee6c 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2877,6 +2877,14 @@ If you continue to receive this message, contact the [SUPPORT_SITE].    <string name="muted_message">      You have blocked this resident. Sending a message will automatically unblock them.    </string> +  <!--Some times string name is getting from the body of server response. +  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.  +  In case of the EXT-3115 issue 'generic' is passed into the gIMMgr::showSessionStartError as a string name. +  Also there are some other places where "generic" is used. +  So, let add string with name="generic" with the same value as "generic_request_error" --> +  <string name="generic"> +    Error making request, please try again later. +  </string>    <string name="generic_request_error">      Error making request, please try again later.    </string> @@ -2904,6 +2912,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].    <string name="message_session_event">      Unable to send your message to the chat session with [RECIPIENT].    </string> +  <string name="mute"> +    Error while moderating. +  </string>    <string name="removed_from_group">      You have been removed from the group.    </string> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml index 9990324d03..102dc0c16d 100644 --- a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml @@ -8,7 +8,7 @@      header_image="Accordion_Off"      header_image_over="Accordion_Over"      header_image_pressed="Accordion_Press" -    header_image_expanded="Accordion_Selected" +    header_image_focused="Accordion_Selected"      header_text_color="LtGray"      font="SansSerif"      /> | 
