diff options
| -rw-r--r-- | indra/llui/lllayoutstack.cpp | 2 | ||||
| -rw-r--r-- | indra/llui/llui.cpp | 12 | ||||
| -rwxr-xr-x | indra/newview/llavataractions.cpp | 30 | ||||
| -rw-r--r-- | indra/newview/llavataractions.h | 10 | ||||
| -rw-r--r-- | indra/newview/llconversationmodel.cpp | 62 | ||||
| -rwxr-xr-x | indra/newview/llconversationmodel.h | 3 | ||||
| -rwxr-xr-x | indra/newview/llconversationview.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/llimconversation.cpp | 23 | ||||
| -rw-r--r-- | indra/newview/llimconversation.h | 2 | ||||
| -rw-r--r-- | indra/newview/llimfloater.cpp | 30 | ||||
| -rw-r--r-- | indra/newview/llimfloatercontainer.cpp | 136 | ||||
| -rw-r--r-- | indra/newview/llimfloatercontainer.h | 3 | ||||
| -rw-r--r-- | indra/newview/llimview.cpp | 12 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_im_session.xml | 2 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_participant_view.xml | 11 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_viewer.xml | 25 | 
16 files changed, 251 insertions, 118 deletions
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index be6d359c9a..1f2496a8e7 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -767,7 +767,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  			{	// freeze new size as fraction  				F32 new_fractional_size = (updated_auto_resize_headroom == 0.f)  					? MAX_FRACTIONAL_SIZE -					: llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim() - 1) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); +					: llclamp(total_visible_fraction * (F32)(new_dim - (panelp->getRelevantMinDim() - 1)) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);  				fraction_given_up -= new_fractional_size - panelp->mFractionalSize;  				fraction_remaining -= panelp->mFractionalSize;  				panelp->mFractionalSize = new_fractional_size; diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 41a948e545..f43409a1ff 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1629,10 +1629,10 @@ void LLUI::initClass(const settings_map_t& settings,  	LLUICtrl::CommitCallbackRegistry::Registrar& reg = LLUICtrl::CommitCallbackRegistry::defaultRegistrar();  	// Callbacks for associating controls with floater visibility: -	reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleInstance, _2, LLSD())); -	reg.add("Floater.ToggleOrBringToFront", boost::bind(&LLFloaterReg::toggleInstanceOrBringToFront, _2, LLSD())); -	reg.add("Floater.Show", boost::bind(&LLFloaterReg::showInstance, _2, LLSD(), FALSE)); -	reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideInstance, _2, LLSD())); +	reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleInstance, _2, LLSD(LLUUID()))); +	reg.add("Floater.ToggleOrBringToFront", boost::bind(&LLFloaterReg::toggleInstanceOrBringToFront, _2, LLSD(LLUUID()))); +	reg.add("Floater.Show", boost::bind(&LLFloaterReg::showInstance, _2, LLSD(LLUUID()), FALSE)); +	reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideInstance, _2, LLSD(LLUUID())));  	// Button initialization callback for toggle buttons  	reg.add("Button.SetFloaterToggle", boost::bind(&LLButton::setFloaterToggle, _1, _2)); @@ -1647,8 +1647,8 @@ void LLUI::initClass(const settings_map_t& settings,  	reg.add("Button.ToggleFloater", boost::bind(&LLButton::toggleFloaterAndSetToggleState, _1, _2));  	// Used by menus along with Floater.Toggle to display visibility as a check-mark -	LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD())); -	LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.IsOpen", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD())); +	LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD(LLUUID()))); +	LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.IsOpen", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD(LLUUID())));  	// Parse the master list of commands  	LLCommandManager::load(); diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 248685b964..3326103d03 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -697,15 +697,15 @@ namespace action_give_inventory  }  // static -void LLAvatarActions::buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string) +void LLAvatarActions::buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string)  {  	llassert(avatar_names.size() > 0); - +	 +	std::sort(avatar_names.begin(), avatar_names.end());  	const std::string& separator = LLTrans::getString("words_separator");  	for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; )  	{ -		LLAvatarName av_name = *it; -		residents_string.append(av_name.mDisplayName); +		residents_string.append((*it).mDisplayName);  		if	(++it == avatar_names.end())  		{  			break; @@ -714,6 +714,28 @@ void LLAvatarActions::buildResidentsString(const std::vector<LLAvatarName> avata  	}  } +// static +void LLAvatarActions::buildResidentsString(const uuid_vec_t& avatar_uuids, std::string& residents_string) +{ +	std::vector<LLAvatarName> avatar_names; +	uuid_vec_t::const_iterator it = avatar_uuids.begin(); +	for (; it != avatar_uuids.end(); ++it) +	{ +		LLAvatarName av_name; +		if (LLAvatarNameCache::get(*it, &av_name)) +		{ +			avatar_names.push_back(av_name); +		} +	} +	 +	// We should check whether the vector is not empty to pass the assertion +	// that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. +	if (!avatar_names.empty()) +	{ +		LLAvatarActions::buildResidentsString(avatar_names, residents_string); +	} +} +  //static  std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()  { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 6e60f624ad..6e1198cd09 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -216,7 +216,15 @@ public:  	 * @param avatar_names - a vector of given avatar names from which resulting string is built  	 * @param residents_string - the resulting string  	 */ -	static void buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string); +	static void buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string); + +	/** +	 * Builds a string of residents' display names separated by "words_separator" string. +	 * +	 * @param avatar_uuids - a vector of given avatar uuids from which resulting string is built +	 * @param residents_string - the resulting string +	 */ +	static void buildResidentsString(const uuid_vec_t& avatar_uuids, std::string& residents_string);  	/**  	 * Opens the chat history for avatar diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 5fc305da81..29e7ac4e12 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -27,6 +27,10 @@  #include "llviewerprecompiledheaders.h" +#include "llavatarnamecache.h" +#include "llavataractions.h" +#include "llevents.h" +#include "llsdutil.h"  #include "llconversationmodel.h"  #include "llimview.h" //For LLIMModel @@ -64,6 +68,14 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod  {  } +void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant) +{ +	LLUUID session_id = (session ? session->getUUID() : LLUUID()); +	LLUUID participant_id = (participant ? participant->getUUID() : LLUUID()); +	LLSD event(LLSDMap("type", event_type)("session_uuid", session_id)("participant_uuid", participant_id)); +	LLEventPumps::instance().obtain("ConversationsEvents").post(event); +} +  // Virtual action callbacks  void LLConversationItem::performAction(LLInventoryModel* model, std::string action)  { @@ -130,12 +142,55 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa  	addChild(participant);  	mIsLoaded = true;  	mNeedsRefresh = true; +	updateParticipantName(participant); +	postEvent("add_participant", this, participant); +} + +void LLConversationItemSession::updateParticipantName(LLConversationItemParticipant* participant) +{ +	// We modify the session name only in the case of an ad-hoc session, exit otherwise (nothing to do) +	if (getType() != CONV_SESSION_AD_HOC) +	{ +		return; +	} +	// Avoid changing the default name if no participant present yet +	if (mChildren.size() == 0) +	{ +		return; +	} +	// Build a string containing the participants names and check if ready for display (we don't want "(waiting)" in there) +	bool all_names_resolved = true; +	uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string +	child_list_t::iterator iter = mChildren.begin(); +	while (iter != mChildren.end()) +	{ +		LLConversationItemParticipant* current_participant = dynamic_cast<LLConversationItemParticipant*>(*iter); +		temp_uuids.push_back(current_participant->getUUID()); +		LLAvatarName av_name; +        if (!LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) +        { +			// If the name is not in the cache yet, bail out +			// Note: we don't bind ourselves to the LLAvatarNameCache event as we are called by +			// onAvatarNameCache() which is itself attached to the same event. +			all_names_resolved = false; +			break; +		} +		iter++; +	} +	if (all_names_resolved) +	{ +		std::string new_session_name; +		LLAvatarActions::buildResidentsString(temp_uuids, new_session_name); +		renameItem(new_session_name); +		postEvent("update_session", this, NULL); +	}  }  void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant)  {  	removeChild(participant);  	mNeedsRefresh = true; +	postEvent("remove_participant", this, participant);  }  void LLConversationItemSession::removeParticipant(const LLUUID& participant_id) @@ -328,10 +383,13 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam  	mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername);  	mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName);  	mNeedsRefresh = true; -	if (mParent) +	LLConversationItemSession* parent_session = dynamic_cast<LLConversationItemSession*>(mParent); +	if (parent_session)  	{ -		mParent->requestSort(); +		parent_session->requestSort(); +		parent_session->updateParticipantName(this);  	} +	postEvent("update_participant", parent_session, this);  }  void LLConversationItemParticipant::dumpDebugData() diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index bc72cd96ea..1d082852f5 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -126,6 +126,8 @@ public:  	void resetRefresh() { mNeedsRefresh = false; }  	bool needsRefresh() { return mNeedsRefresh; } +	void postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant); +	      void buildParticipantMenuOptions(menuentry_vec_t&   items);  protected: @@ -147,6 +149,7 @@ public:      LLPointer<LLUIImage> getIcon() const { return NULL; }  	void setSessionID(const LLUUID& session_id) { mUUID = session_id; mNeedsRefresh = true; }  	void addParticipant(LLConversationItemParticipant* participant); +	void updateParticipantName(LLConversationItemParticipant* participant);  	void removeParticipant(LLConversationItemParticipant* participant);  	void removeParticipant(const LLUUID& participant_id);  	void clearParticipants(); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 112c38d8b8..f9a3a05e59 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -183,10 +183,8 @@ void LLConversationViewSession::draw()  	// draw highlight for selected items  	drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); -	// draw children if root folder, or any other folder that is open or animating to closed state -	bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) -						 || isOpen() -						 || mCurHeight != mTargetHeight; +	// Draw children if root folder, or any other folder that is open. Do not draw children when animating to closed state or you get rendering overlap. +	bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) || isOpen();  	for (folders_t::iterator iter = mFolders.begin();  		iter != mFolders.end();) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 2ad7f9b193..9f3c6d0f3d 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -393,7 +393,7 @@ void LLIMConversation::updateHeaderAndToolbar()  	// prevent start conversation before its container      LLIMFloaterContainer::getInstance(); -	bool is_torn_off = !getHost(); +	bool is_torn_off = checkIfTornOff();  	if (!is_torn_off)  	{  		hideAllStandardButtons(); @@ -505,16 +505,12 @@ void LLIMConversation::onSlide(LLIMConversation* self)  /*virtual*/  void LLIMConversation::onOpen(const LLSD& key)  { -	LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); -    bool is_hosted = !!host_floater; -	if (is_hosted) +	if (!checkIfTornOff())  	{ +		LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost());  		// Show the messages pane when opening a floater hosted in the Conversations  		host_floater->collapseMessagesPane(false);  	} - -	setTornOff(!is_hosted); -	updateHeaderAndToolbar();  }  // virtual @@ -546,3 +542,16 @@ bool LLIMConversation::isChatMultiTab()  	// Restart is required in order to change chat window type.  	return true;  } + +bool LLIMConversation::checkIfTornOff() +{ +	bool isTorn = !getHost(); +	 +	if (isTorn != isTornOff()) +	{ +		setTornOff(isTorn); +		updateHeaderAndToolbar(); +	} + +	return isTorn; +} diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index c54081d316..0960d6db88 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -138,6 +138,8 @@ private:  	 */  	void reshapeChatHistory(); +	bool checkIfTornOff(); +  	LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called.  	bool mHadFocus; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a1ed1e0b01..a8add9c6ab 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -60,10 +60,6 @@  #include "llnotificationmanager.h"  #include "llautoreplace.h" -/// Helper function to resolve resident names from given uuids -/// and form a string of names separated by "words_separator". -static void build_names_string(const uuid_vec_t& uuids, std::string& names_string); -  floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal;  LLIMFloater::LLIMFloater(const LLUUID& session_id) @@ -476,7 +472,7 @@ void LLIMFloater::addP2PSessionParticipants(const LLSD& notification, const LLSD  void LLIMFloater::sendParticipantsAddedNotification(const uuid_vec_t& uuids)  {  	std::string names_string; -	build_names_string(uuids, names_string); +	LLAvatarActions::buildResidentsString(uuids, names_string);  	LLStringUtil::format_map_t args;  	args["[NAME]"] = names_string; @@ -581,7 +577,7 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl)  	if (all_names_resolved)  	{  		std::string ui_title; -		build_names_string(temp_uuids, ui_title); +		LLAvatarActions::buildResidentsString(temp_uuids, ui_title);  		updateSessionName(ui_title, ui_title);  	}  } @@ -1332,25 +1328,3 @@ boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floate  {  	return LLIMFloater::sIMFloaterShowedSignal.connect(cb);  } - -// static -void build_names_string(const uuid_vec_t& uuids, std::string& names_string) -{ -	std::vector<LLAvatarName> avatar_names; -	uuid_vec_t::const_iterator it = uuids.begin(); -	for (; it != uuids.end(); ++it) -	{ -		LLAvatarName av_name; -		if (LLAvatarNameCache::get(*it, &av_name)) -		{ -			avatar_names.push_back(av_name); -		} -	} - -	// We should check whether the vector is not empty to pass the assertion -	// that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. -	if (!avatar_names.empty()) -	{ -		LLAvatarActions::buildResidentsString(avatar_names, names_string); -	} -} diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4af170b3db..5f111b39d4 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -50,6 +50,7 @@  #include "llcallbacklist.h"  #include "llworld.h" +#include "llsdserialize.h"  //  // LLIMFloaterContainer  // @@ -57,6 +58,7 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)  :	LLMultiFloater(seed),  	mExpandCollapseBtn(NULL),  	mConversationsRoot(NULL), +	mConversationsEventStream("ConversationsEvents"),  	mInitialized(false)  {      mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); @@ -77,6 +79,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)  LLIMFloaterContainer::~LLIMFloaterContainer()  { +	mConversationsEventStream.stopListening("ConversationsRefresh"); +  	gIdleCallbacks.deleteFunction(idle, this);  	mNewMessageConnection.disconnect(); @@ -155,6 +159,9 @@ BOOL LLIMFloaterContainer::postBuild()  	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);      mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); +	// Add listener to conversation model events +	mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLIMFloaterContainer::onConversationModelEvent, this, _1)); +  	// a scroller for folder view  	LLRect scroller_view_rect = mConversationsListPanel->getRect();  	scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); @@ -397,62 +404,81 @@ void LLIMFloaterContainer::idle(void* user_data)  	self->mConversationsRoot->update();  } -void LLIMFloaterContainer::draw() +bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event)  { -	// CHUI Notes -	// Currently, the model is not responsible for creating the view which is a good thing. This means that -	// the model could change substantially and the view could decide to echo only a portion of this model. -	// Consequently, the participant views need to be created either by the session view or by the container panel. -	// For the moment, we create them here (which makes for complicated code...) to conform to the pattern -	// implemented in llinventorypanel.cpp (see LLInventoryPanel::buildNewViews()). -	// The best however would be to have an observer on the model so that we would not pool on each draw to know -	// if the view needs refresh. The current implementation (testing for change on draw) is less -	// efficient perf wise than a listener/observer scheme. We will implement that shortly. +	// For debug only +	//std::ostringstream llsd_value; +	//llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl; +	//llinfos << "Merov debug : onConversationModelEvent, event = " << llsd_value.str() << llendl; +	// end debug -	// On each session in mConversationsItems -	for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) +	// Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that +	// the model could change substantially and the view could echo only a portion of this model (though currently the  +	// conversation view does echo the conversation model 1 to 1). +	// Consequently, the participant views need to be created either by the session view or by the container panel. +	// For the moment, we create them here, at the container level, to conform to the pattern implemented in llinventorypanel.cpp  +	// (see LLInventoryPanel::buildNewViews()). + +	std::string type = event.get("type").asString(); +	LLUUID session_id = event.get("session_uuid").asUUID(); +	LLUUID participant_id = event.get("participant_uuid").asUUID(); + +	LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); +	if (!session_view)  	{ -		// Get the current session descriptors -		LLConversationItem* session_model = it_session->second; -		LLUUID session_id = it_session->first; -		LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); -		// If the session model has been changed, refresh the corresponding view -		if (session_model->needsRefresh()) +		// We skip events that are not associated to a session +		return false; +	} +	LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); + +	if (type == "remove_participant") +	{ +		if (participant_view)  		{ +			session_view->extractItem(participant_view); +			delete participant_view;  			session_view->refresh(); +			mConversationsRoot->arrangeAll();  		} -		// Iterate through each model participant child -		LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); -		LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); -		while (current_participant_model != end_participant_model) +	} +	else if (type == "add_participant") +	{ +		if (!participant_view)  		{ -			LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); -			LLUUID participant_id = participant_model->getUUID(); -			LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); -			// Is there a corresponding view? If not create it -			if (!participant_view) -			{ -				participant_view = createConversationViewParticipant(participant_model); -				participant_view->addToFolder(session_view); -				participant_view->setVisible(TRUE); -			} -			else -			// Else, see if it needs refresh +			LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); +			if (session_model)  			{ -				if (participant_model->needsRefresh()) +				LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id); +				if (participant_model)  				{ -					participant_view->refresh(); +					participant_view = createConversationViewParticipant(participant_model); +					participant_view->addToFolder(session_view); +					participant_view->setVisible(TRUE);  				}  			} -			// Reset the need for refresh -			session_model->resetRefresh(); -			mConversationViewModel.requestSortAll(); -			mConversationsRoot->arrangeAll(); -			// Next participant -			current_participant_model++; + +		} +	} +	else if (type == "update_participant") +	{ +		if (participant_view) +		{ +			participant_view->refresh();  		}  	} +	else if (type == "update_session") +	{ +		session_view->refresh(); +	} +	 +	mConversationViewModel.requestSortAll(); +	mConversationsRoot->arrangeAll(); +	return false; +} + +void LLIMFloaterContainer::draw() +{  	if (mTabContainer->getTabCount() == 0)  	{  		// Do not close the container when every conversation is torn off because the user @@ -527,12 +553,25 @@ void LLIMFloaterContainer::collapseMessagesPane(bool collapse)  		gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed());  	} +	// Save left pane rectangle before collapsing/expanding right pane. +	LLRect prevRect = mConversationsPane->getRect(); +  	// Show/hide the messages pane.  	mConversationsStack->collapsePanel(mMessagesPane, collapse); +	if (!collapse) +	{ +		// Make sure layout is updated before resizing conversation pane. +		mConversationsStack->updateLayout(); +	} +  	updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); +	if (!collapse) +	{ +		// Restore conversation's pane previous width after expanding messages pane. +		mConversationsPane->setTargetDim(prevRect.getWidth()); +	}  } -  void LLIMFloaterContainer::collapseConversationsPane(bool collapse)  {  	if (mConversationsPane->isCollapsed() == collapse) @@ -862,7 +901,13 @@ void LLIMFloaterContainer::doToSelectedConversation(const std::string& command,          }          else if("chat_history" == command)          { -            LLAvatarActions::viewChatHistory(conversationItem->getUUID()); +			const LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(conversationItem->getUUID()); + +			if (NULL != session) +			{ +				const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; +				LLFloaterReg::showInstance("preview_conversation", session_id, true); +			}          }          else          { @@ -1089,7 +1134,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid)  	removeConversationListItem(uuid,false);  	// Create a conversation session model -	LLConversationItem* item = NULL; +	LLConversationItemSession* item = NULL;  	LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid));  	if (speaker_manager)  	{ @@ -1101,6 +1146,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid)  		return;  	}  	item->renameItem(display_name); +	item->updateParticipantName(NULL);  	mConversationsItems[uuid] = item; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 76e468f979..ceb054dfa3 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -31,6 +31,7 @@  #include <vector>  #include "llimview.h" +#include "llevents.h"  #include "llfloater.h"  #include "llmultifloater.h"  #include "llavatarpropertiesprocessor.h" @@ -140,6 +141,7 @@ public:  private:  	LLConversationViewSession* createConversationItemWidget(LLConversationItem* item);  	LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); +	bool onConversationModelEvent(const LLSD& event);  	// Conversation list data  	LLPanel* mConversationsListPanel;	// This is the main widget we add conversation widget to @@ -147,6 +149,7 @@ private:  	conversations_widgets_map mConversationsWidgets;  	LLConversationViewModel mConversationViewModel;  	LLFolderView* mConversationsRoot; +	LLEventStream mConversationsEventStream;   };  #endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b45903835a..a604c884ca 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -643,6 +643,12 @@ void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, con  	{  		session->sessionInitReplyReceived(new_session_id); +		LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id); +		if (im_floater) +		{ +			im_floater->sessionInitReplyReceived(new_session_id); +		} +  		if (old_session_id != new_session_id)  		{  			mId2SessionMap.erase(old_session_id); @@ -651,12 +657,6 @@ void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, con  			gIMMgr->notifyObserverSessionIDUpdated(old_session_id, new_session_id);  		} -		LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id); -		if (im_floater) -		{ -			im_floater->sessionInitReplyReceived(new_session_id); -		} -  		// auto-start the call on session initialization?  		if (session->mStartCallOnInitialize)  		{ diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 5c74f7f9bb..8cd0463de8 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -246,7 +246,7 @@           parse_highlights="true"           parse_urls="true"         	 width="230" -       	 left="0"> +       	 left="5">          </chat_history>              </layout_panel>             </layout_stack> diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 0043c14479..6fa0707eea 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -59,17 +59,6 @@           function="IMFloaterContainer.Check"           parameter="sort_participants_by_recent" />      </menu_item_check> -    <menu_item_check -     label="Sort participants by distance from you" -     layout="topleft" -     name="sort_participants_by_distance"> -        <on_click -         function="IMFloaterContainer.Action" -         parameter="sort_participants_by_distance" /> -        <on_check -         function="IMFloaterContainer.Check" -         parameter="sort_participants_by_distance" /> -    </menu_item_check>      <menu_item_separator       layout="topleft" />      <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 88b30c8272..c805b6db42 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -218,8 +218,18 @@       label="Communicate"       name="Communicate"       tear_off="true"> -        <menu_item_check -         label="Chat..." +       <menu_item_check +         label="Conversations..." +         name="Conversations"> +            <menu_item_check.on_check +             function="Floater.IsOpen" +             parameter="im_container" /> +            <menu_item_check.on_click +             function="Floater.ToggleOrBringToFront" +             parameter="im_container" /> +	</menu_item_check> +	<menu_item_check +         label="Nearby Chat..."           name="Nearby Chat"           shortcut="control|H"           use_mac_ctrl="true"> @@ -244,6 +254,17 @@               parameter="speak" />          </menu_item_check>          <menu_item_check +         label="Conversations Log..." +         name="ConversationsLog"> +            <menu_item_check.on_check +             function="Floater.Visible" +             parameter="conversation" /> +            <menu_item_check.on_click +             function="Floater.Toggle" +             parameter="conversation" /> +        </menu_item_check> +        <menu_item_separator/> +        <menu_item_check           label="Voice morphing..."           name="ShowVoice"           visibility_control="VoiceMorphingEnabled">  | 
